From 4d00c92eb2954b45dd9417ed0b41928bb2145c41 Mon Sep 17 00:00:00 2001 From: Peter Matta <mattapet@fit.cvut.cz> Date: Wed, 25 Apr 2018 23:25:04 +0200 Subject: [PATCH] Updated defaul interface for compiler --- include/CMakeLists.txt | 1 - include/dusk/AST/ASTContext.h | 84 ++++++++++++++++++ include/dusk/AST/ASTVisitor.h | 2 - include/dusk/AST/CMakeLists.txt | 1 + include/dusk/AST/Pattern.h | 5 +- include/dusk/Basic/LLVM.h | 4 +- include/dusk/Frontend/CMakeLists.txt | 6 +- include/dusk/Frontend/Compiler.h | 51 ----------- include/dusk/Frontend/CompilerInstance.h | 85 +++++++++++++++++++ include/dusk/Frontend/CompilerInvocation.h | 57 +++++++++++++ .../Frontend/{InputFile.h => SourceFile.h} | 10 ++- include/dusk/Parse/Parser.h | 51 +++++++---- .../Formatter.h => lib/AST/ASTContext.cpp | 18 +--- lib/AST/ASTPrinter.cpp | 17 ++-- lib/AST/CMakeLists.txt | 1 + lib/Frontend/CMakeLists.txt | 6 +- lib/Frontend/Compiler.cpp | 80 ----------------- lib/Frontend/CompilerInstance.cpp | 50 +++++++++++ lib/Frontend/CompilerInvocation.cpp | 42 +++++++++ lib/Frontend/Formatter.cpp | 0 lib/Frontend/InputFile.cpp | 20 ----- lib/IRGen/CMakeLists.txt | 2 - lib/IRGen/TopLevelExpr.cpp | 0 lib/IRGen/TopLevelExpr.h | 0 lib/Parser/ParseDecl.cpp | 8 +- lib/Parser/ParseExpr.cpp | 20 ++--- lib/Parser/ParsePattern.cpp | 4 +- lib/Parser/ParseStmt.cpp | 20 ++--- lib/Parser/Parser.cpp | 21 +++-- tools/dusk-format/main.cpp | 35 ++++++-- 30 files changed, 448 insertions(+), 253 deletions(-) create mode 100644 include/dusk/AST/ASTContext.h delete mode 100644 include/dusk/Frontend/Compiler.h create mode 100644 include/dusk/Frontend/CompilerInstance.h create mode 100644 include/dusk/Frontend/CompilerInvocation.h rename include/dusk/Frontend/{InputFile.h => SourceFile.h} (82%) rename include/dusk/Frontend/Formatter.h => lib/AST/ASTContext.cpp (50%) delete mode 100644 lib/Frontend/Compiler.cpp create mode 100644 lib/Frontend/CompilerInstance.cpp create mode 100644 lib/Frontend/CompilerInvocation.cpp delete mode 100644 lib/Frontend/Formatter.cpp delete mode 100644 lib/Frontend/InputFile.cpp delete mode 100644 lib/IRGen/TopLevelExpr.cpp delete mode 100644 lib/IRGen/TopLevelExpr.h diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 0c39d4d..2cbe7c7 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory(dusk) -link_directories(dusk) set(HEADERS ${HEADERS} diff --git a/include/dusk/AST/ASTContext.h b/include/dusk/AST/ASTContext.h new file mode 100644 index 0000000..caf17fd --- /dev/null +++ b/include/dusk/AST/ASTContext.h @@ -0,0 +1,84 @@ +//===--- ASTContext.h - Object holding AST state ----------------*- C++ -*-===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#ifndef DUSK_AST_CONTEXT_H +#define DUSK_AST_CONTEXT_H + +#include "dusk/Basic/LLVM.h" +#include "dusk/AST/ASTNode.h" +#include "dusk/AST/Pattern.h" +#include "dusk/AST/Type.h" +#include "llvm/ADT/ArrayRef.h" +#include <memory> +#include <vector> + +namespace dusk { +class Decl; +class ModuleDecl; +class Expr; +class Stmt; +class ASTNode; +class Pattern; +class Type; +class VoidType; +class IntType; + +/// This class owns all of the nodes, which are part of the AST. +class ASTContext { + std::vector<std::unique_ptr<ASTNode>> Nodes; + std::vector<std::unique_ptr<Pattern>> Patterns; + std::vector<std::unique_ptr<Type>> Types; + + bool IsError = false; + + ModuleDecl *RootModule; + +public: + ASTContext() = default; + + /// Returns pointer to the root module of the AST. + ModuleDecl *getRootModule() const { return RootModule; } + + /// Sets the root module of the AST. + void setRootModule(ModuleDecl *RM) { RootModule = RM; } + + /// Returns \c true if \c setError has been called upon the context, \c false + /// otherwise. + bool isError() const { return IsError; } + + /// Sets AST error state to \c true. + /// + /// \node This action is ireversible. + void setError() { IsError = true; } + + ArrayRef<std::unique_ptr<ASTNode>> getNodes() const { return Nodes; } + + ArrayRef<std::unique_ptr<Pattern>> getPatterns() const { return Patterns; } + + ArrayRef<std::unique_ptr<Type>> getTypes() const { return Types; } + + template <typename T> T *pushNode(std::unique_ptr<T> &&Node) { + Nodes.push_back(std::move(Node)); + return static_cast<T *>(Nodes.back().get()); + } + + template <typename T> T *pushPattern(std::unique_ptr<T> &&Pattern) { + Patterns.push_back(std::move(Pattern)); + return static_cast<T *>(Patterns.back().get()); + } + + template <typename T> T *pushType(std::unique_ptr<T> &&Type) { + Types.push_back(std::move(Type)); + return static_cast<T *>(Patterns.back().get()); + } +}; + +} // namespace dusk + +#endif /* DUSK_AST_CONTEXT_H */ diff --git a/include/dusk/AST/ASTVisitor.h b/include/dusk/AST/ASTVisitor.h index af8db93..0bd1a5d 100644 --- a/include/dusk/AST/ASTVisitor.h +++ b/include/dusk/AST/ASTVisitor.h @@ -45,8 +45,6 @@ public: return visit(E); if (auto *S = dynamic_cast<Stmt *>(N)) return visit(S); - if (auto *P = dynamic_cast<Pattern *>(N)) - return visit(P); llvm_unreachable("Unexpected node"); } diff --git a/include/dusk/AST/CMakeLists.txt b/include/dusk/AST/CMakeLists.txt index 98d812f..7321e37 100644 --- a/include/dusk/AST/CMakeLists.txt +++ b/include/dusk/AST/CMakeLists.txt @@ -1,4 +1,5 @@ set(HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/ASTContext.h ${CMAKE_CURRENT_SOURCE_DIR}/ASTNode.h ${CMAKE_CURRENT_SOURCE_DIR}/ASTPrinter.h ${CMAKE_CURRENT_SOURCE_DIR}/ASTVisitor.h diff --git a/include/dusk/AST/Pattern.h b/include/dusk/AST/Pattern.h index 4ab8409..4499d99 100644 --- a/include/dusk/AST/Pattern.h +++ b/include/dusk/AST/Pattern.h @@ -25,7 +25,7 @@ class ParamDecl; /// Pattern description. enum struct PatternKind { Expr, Variable }; -class Pattern : public ASTNode { +class Pattern { /// Pattern type. PatternKind Kind; @@ -34,6 +34,9 @@ public: PatternKind getKind() const { return Kind; } virtual size_t count() const = 0; + virtual SMRange getSourceRange() const = 0; + SMLoc getLocStart() { return getSourceRange().Start; } + SMLoc getLocEnd() { return getSourceRange().End; } }; /// Expression pattern diff --git a/include/dusk/Basic/LLVM.h b/include/dusk/Basic/LLVM.h index 1d0d2a9..a2122f5 100644 --- a/include/dusk/Basic/LLVM.h +++ b/include/dusk/Basic/LLVM.h @@ -25,7 +25,7 @@ template <typename T> class Optional; // Support class SMLoc; class SMRange; -class SourceMrg; +class SourceMgr; class SMDiagnostic; class SMFixIt; @@ -48,7 +48,7 @@ using llvm::Optional; // Support using llvm::SMLoc; using llvm::SMRange; -using llvm::SourceMrg; +using llvm::SourceMgr; using llvm::SMDiagnostic; using llvm::SMFixIt; diff --git a/include/dusk/Frontend/CMakeLists.txt b/include/dusk/Frontend/CMakeLists.txt index 63b3453..154c1fd 100644 --- a/include/dusk/Frontend/CMakeLists.txt +++ b/include/dusk/Frontend/CMakeLists.txt @@ -1,7 +1,7 @@ set(HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/Compiler.h - ${CMAKE_CURRENT_SOURCE_DIR}/Formatter.h - ${CMAKE_CURRENT_SOURCE_DIR}/InputFile.h + ${CMAKE_CURRENT_SOURCE_DIR}/CompilerInstance.h + ${CMAKE_CURRENT_SOURCE_DIR}/CompilerInvocation.h + ${CMAKE_CURRENT_SOURCE_DIR}/SourceFile.h ${HEADERS} PARENT_SCOPE ) diff --git a/include/dusk/Frontend/Compiler.h b/include/dusk/Frontend/Compiler.h deleted file mode 100644 index 57d4cad..0000000 --- a/include/dusk/Frontend/Compiler.h +++ /dev/null @@ -1,51 +0,0 @@ -//===--- Compiler.h - Dusk compiler class -----------------------*- C++ -*-===// -// -// dusk-lang -// This source file is part of a dusk-lang project, which is a semestral -// assignement for BI-PJP course at Czech Technical University in Prague. -// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. -// -//===----------------------------------------------------------------------===// - -#ifndef DUSK_COMPILER_H -#define DUSK_COMPILER_H - -#include "dusk/Basic/LLVM.h" -#include "dusk/AST/Diagnostics.h" -#include "dusk/AST/Diagnostics.h" -#include "dusk/Frontend/InputFile.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_os_ostream.h" -#include <vector> -#include <memory> - -namespace llvm { -class Module; -} - -namespace dusk { -class ParserResult; - -class Compiler : public DiagnosticConsumer { - llvm::SourceMgr SourceManager; - - DiagnosticEngine Engine; - - std::vector<std::unique_ptr<InputFile>> InputFiles; - - /// Diagnostic output stream - llvm::raw_os_ostream OS; - -public: - Compiler(std::vector<StringRef> Filenames); - - void Compile(); - void Lex(); - - void consume(SMDiagnostic &Diag); -}; - -} // namesapce dusk - -#endif /* DUSK_COMPILER_H */ diff --git a/include/dusk/Frontend/CompilerInstance.h b/include/dusk/Frontend/CompilerInstance.h new file mode 100644 index 0000000..41af881 --- /dev/null +++ b/include/dusk/Frontend/CompilerInstance.h @@ -0,0 +1,85 @@ +//===--- CompilerInstance.h - Dusk compiler configuration -----*- C++ -*-===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#include "dusk/Basic/LLVM.h" +#include "dusk/AST/ASTContext.h" +#include "dusk/AST/Diagnostics.h" +#include "dusk/Frontend/CompilerInvocation.h" +#include "dusk/Frontend/SourceFile.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/SourceMgr.h" +#include <memory> + +#ifndef DUSK_COMPILER_INSTANCE_H +#define DUSK_COMPILER_INSTANCE_H + +namespace dusk { +class ModuleDecl; + +/// Encapsulation of compiler state and execution. +class CompilerInstance { + CompilerInvocation Invocation; + SourceMgr SourceManager; + DiagnosticEngine Diag{SourceManager}; + + /// Compilation context. + std::unique_ptr<ASTContext> Context; + + /// Main compilation module + ModuleDecl *MainModule = nullptr; + +public: + /// Constructs a default compiler instance. + CompilerInstance() = default; + + /// Retuns compilers source manager. + SourceMgr &getSourceManager() { return SourceManager; } + + /// Returns compilers diagnostics. + DiagnosticEngine &getDiags() { return Diag; } + + /// Returns AST context of current compilation + ASTContext &getContext() { return *Context; } + + /// Returns \c true, if copmiler instance has an AST context, \c false + /// otherwise. + bool hasASTContext() const { return Context != nullptr; } + + /// Retuns parsed file as a module. + ModuleDecl *getModule(); + + /// Returns the input file. + SourceFile *getInputFile(); + + /// Compiles a source file. + void performCompilation(); + + /// Parses file and performs a semantic analysis. + void performSema(); + + /// Parses input file without performing any semantic analysis. + void performParseOnly(); + + /// Free AST context to enable reuse of current compiler instance. + void freeContext(); + + /// Reset compiler instance with new configuration. + void reset(CompilerInvocation &&I); + +private: + // Explicitly forbid copying of any kind. + CompilerInstance(const CompilerInstance &other) = delete; + CompilerInstance &operator=(const CompilerInstance &other) = delete; + CompilerInstance(CompilerInstance &&other) = delete; + CompilerInstance &operator=(CompilerInstance &&other) = delete; +}; + +} // namespace dusk + +#endif /* DUSK_COMPILER_INSTANCE_H */ diff --git a/include/dusk/Frontend/CompilerInvocation.h b/include/dusk/Frontend/CompilerInvocation.h new file mode 100644 index 0000000..777081d --- /dev/null +++ b/include/dusk/Frontend/CompilerInvocation.h @@ -0,0 +1,57 @@ +//===--- CompilerInvocation.h - Dusk compiler configuration -----*- C++ -*-===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#ifndef DUSK_COMPILER_INVOCATION_H +#define DUSK_COMPILER_INVOCATION_H + +#include "dusk/Basic/LLVM.h" +#include "dusk/AST/Diagnostics.h" +#include "dusk/Frontend/SourceFile.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/SourceMgr.h" +#include <vector> +#include <memory> + +namespace dusk { + +/// Compiler configuration. +class CompilerInvocation { + + /// Minimum build target + llvm::Triple Target; + + std::unique_ptr<SourceFile> InputFile; + + StringRef ModuleName; + StringRef OutputName; + + bool IsQuiet; + +public: + CompilerInvocation(); + + void setArgs(SourceMgr &SM, DiagnosticEngine &Diag, StringRef InFile, + StringRef OutFile, bool IsQuiet); + + StringRef getTargetTriple() const { return Target.str(); } + + SourceFile *getInputFile() const { return InputFile.get(); } + + void setModuleName(StringRef Name) { ModuleName = Name; } + + StringRef getModuleName() const { return ModuleName; } + + StringRef getOutputFilename() const { return OutputName; } +}; + +} // namespace dusk + +#endif /* DUSK_COMPILER_INVOCATION_H */ diff --git a/include/dusk/Frontend/InputFile.h b/include/dusk/Frontend/SourceFile.h similarity index 82% rename from include/dusk/Frontend/InputFile.h rename to include/dusk/Frontend/SourceFile.h index d84b670..20c474f 100644 --- a/include/dusk/Frontend/InputFile.h +++ b/include/dusk/Frontend/SourceFile.h @@ -1,4 +1,4 @@ -//===--- InputFile.h --------------------------------------------*- C++ -*-===// +//===--- SourceFile.h -------------------------------------------*- C++ -*-===// // // dusk-lang // This source file is part of a dusk-lang project, which is a semestral @@ -23,15 +23,17 @@ namespace dusk { /// Upon construction of a new \c InputFile class, the object tries to load /// the provided file and pass it to provided \c SourceMgr instance, /// to register the as a new source buffer. -class InputFile { +class SourceFile { unsigned BufferID; std::string Filename; llvm::MemoryBuffer *Buffer; - llvm::SourceMgr &SourceManager; public: /// \brief Opens and reads a file with provided name. - InputFile(llvm::SourceMgr &SM, const StringRef F); + SourceFile(unsigned ID, llvm::MemoryBuffer *B, StringRef F) + : BufferID(ID), Filename(F), Buffer(B) { + assert(!Filename.empty() && "Filename must not be an empty string."); + } /// \bried Returns an ID of the opened buffer. unsigned bufferID() const { return BufferID; } diff --git a/include/dusk/Parse/Parser.h b/include/dusk/Parse/Parser.h index 8428099..8e1399e 100644 --- a/include/dusk/Parse/Parser.h +++ b/include/dusk/Parse/Parser.h @@ -15,6 +15,7 @@ #define DUSK_PARSER_H #include "dusk/AST/ASTNode.h" +#include "dusk/AST/ASTContext.h" #include "dusk/AST/Decl.h" #include "dusk/AST/Expr.h" #include "dusk/AST/Stmt.h" @@ -24,7 +25,7 @@ #include "dusk/Parse/Token.h" #include "dusk/Parse/Lexer.h" #include "dusk/Parse/ParserResult.h" -#include "dusk/Frontend/InputFile.h" +#include "dusk/Frontend/SourceFile.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" @@ -32,9 +33,14 @@ namespace dusk { /// The main class used for parsing a dusk-lang (.dusk) source file. class Parser { + ASTContext &Context; + llvm::SourceMgr &SourceManager; - InputFile &SourceFile; - DiagnosticEngine &Engine; + + SourceFile &SF; + + DiagnosticEngine &Diag; + Lexer *L; /// Parsing result. @@ -47,7 +53,10 @@ class Parser { SMLoc PreviousLoc; public: - Parser(llvm::SourceMgr &SM, InputFile &SF, DiagnosticEngine &Engine, + Parser(ASTContext &C, + SourceMgr &SM, + SourceFile &SF, + DiagnosticEngine &Diag, unsigned BufferID); ~Parser(); @@ -79,17 +88,14 @@ public: diag::DiagID ID = diag::DiagID::unexpected_token); /// Main parsing method. - /// - /// \return A pointer to the root of the AST representing parsed - /// source file. - ParserResult &&parse(); + ModuleDecl *parseModule(); private: - //===------------------------------------------------------------------------=== - // - // Recursive descent parsing methods - // - //===------------------------------------------------------------------------=== +//===------------------------------------------------------------------------=== +// +// Recursive descent parsing methods +// +//===------------------------------------------------------------------------=== ASTNode *parseGlobal(); @@ -170,9 +176,24 @@ private: /// Creates and adds a new instance of \c ASTNode to the parser result /// and returns a pointer to it. - template <typename Node, typename... Args> Node *make(Args &&... args) { + template <typename Node, typename... Args> Node *makeNode(Args &&... args) { auto N = std::unique_ptr<Node>(new Node(std::forward<Args>(args)...)); - return R.push(std::move(N)); + return Context.pushNode(std::move(N)); + } + + /// Creates and adds a new instance of \c ASTNode to the parser result + /// and returns a pointer to it. + template <typename Pattern, typename... Args> + Pattern *makePattern(Args &&... args) { + auto P = std::unique_ptr<Pattern>(new Pattern(std::forward<Args>(args)...)); + return Context.pushPattern(std::move(P)); + } + + /// Creates and adds a new instance of \c ASTNode to the parser result + /// and returns a pointer to it. + template <typename Type, typename... Args> Type *makeType(Args &&... args) { + auto T = std::unique_ptr<Type>(new Type(std::forward<Args>(args)...)); + return Context.pushType(std::move(T)); } }; diff --git a/include/dusk/Frontend/Formatter.h b/lib/AST/ASTContext.cpp similarity index 50% rename from include/dusk/Frontend/Formatter.h rename to lib/AST/ASTContext.cpp index 22ea10b..42023b4 100644 --- a/include/dusk/Frontend/Formatter.h +++ b/lib/AST/ASTContext.cpp @@ -1,4 +1,4 @@ -//===--- Formatter.h - Dusk language formatter ------------------*- C++ -*-===// +//===--- ASTContext.cpp ---------------------------------------------------===// // // dusk-lang // This source file is part of a dusk-lang project, which is a semestral @@ -7,19 +7,5 @@ // //===----------------------------------------------------------------------===// -#ifndef DUSK_FORMATTER_H -#define DUSK_FORMATTER_H -#include "dusk/AST/ASTNode.h" -#include "llvm/Support/raw_ostream.h" - -namespace dusk { - -class Formatter { -public: - void format(ASTNode *N, raw_ostream &OS); -}; - -} // namespace dusk - -#endif /* DUSK_FORMATTER_H */ +#include "dusk/AST/ASTContext.h" diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 2bf6346..201dd44 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -15,7 +15,6 @@ #include "dusk/AST/Type.h" #include "dusk/AST/ASTVisitor.h" #include "dusk/Basic/TokenDefinition.h" -#include "dusk/Frontend/Formatter.h" using namespace dusk; @@ -499,11 +498,11 @@ StreamPrinter::StreamPrinter(raw_ostream &OS) : OS(OS) {} void StreamPrinter::printText(StringRef Text) { OS << Text; } -// MARK: - Formatter - -void Formatter::format(ASTNode *N, raw_ostream &OS) { - PrettyPrinter pp(OS); - PrintAST p(pp); - p.ASTVisitor::visit(N); -} - +//// MARK: - Formatter +// +//void Formatter::format(ASTNode *N, raw_ostream &OS) { +// PrettyPrinter pp(OS); +// PrintAST p(pp); +// p.ASTVisitor::visit(N); +//} +// diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 450cd4d..d7cf88a 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -1,4 +1,5 @@ set(SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/ASTContext.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ASTNode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ASTPrinter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ASTWalker.cpp diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 04705cb..9164a59 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -1,7 +1,7 @@ set(SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/Compiler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Formatter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/InputFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CompilerInstance.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/CompilerInvocation.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/SourceFile.cpp ${SOURCE} PARENT_SCOPE ) diff --git a/lib/Frontend/Compiler.cpp b/lib/Frontend/Compiler.cpp deleted file mode 100644 index 18b7851..0000000 --- a/lib/Frontend/Compiler.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "dusk/Frontend/Compiler.h" -#include "dusk/Frontend/Formatter.h" -#include "dusk/Parse/Lexer.h" -#include "dusk/Basic/TokenDefinition.h" -#include "dusk/Parse/Parser.h" -#include "dusk/IRGen/IRGenerator.h" -#include "llvm/Support/raw_os_ostream.h" - -#include "llvm/Analysis/Passes.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/raw_ostream.h" - -#include <iostream> -#include <vector> - -using namespace dusk; - -Compiler::Compiler(std::vector<StringRef> Filenames) - : Engine(SourceManager), OS(raw_os_ostream(std::cerr)) { - Engine.addConsumer(this); - for (auto &F : Filenames) { - auto File = std::make_unique<InputFile>(SourceManager, F); - InputFiles.push_back(std::move(File)); - } -} - -void Compiler::Compile() { - Formatter F; - raw_os_ostream OS(std::cout); - std::vector<ParserResult> Results; - - for (auto &&File : InputFiles) { - Parser P(SourceManager, *File, Engine, File->bufferID()); - auto R = P.parse(); - // Stop compilation after error encounterment - if (R.isError()) - return; - Results.push_back(std::move(R)); - } - -// for (auto &&R : Results) -// F.format(R.getRoot(), OS); - irgen::IRGenerator IRGen(Engine); - auto Module = IRGen.gen(Results.front().getRoot()); - if (!Module) - return; - - Module->print(llvm::errs(), nullptr); - llvm::verifyModule(*Module); - std::cout << std::endl; -} - -void Compiler::Lex() { - for (auto &&File : InputFiles) { - Lexer L(SourceManager, File->bufferID(), &Engine, true); - Token T; - do { - L.lex(T); - if (T.is(tok::unknown)) { - return; - } - } while (T.isNot(tok::eof)); - } -} - -void Compiler::consume(llvm::SMDiagnostic &Diag) { - Diag.print("duskc", OS); -} - diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp new file mode 100644 index 0000000..8cdd130 --- /dev/null +++ b/lib/Frontend/CompilerInstance.cpp @@ -0,0 +1,50 @@ +//===--- CompilerInstance.cpp -------------------------------------------===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#include "dusk/Frontend/CompilerInstance.h" + +#include "dusk/Parse/Parser.h" + +using namespace dusk; + +ModuleDecl *CompilerInstance::getModule() { + if (hasASTContext() && !Context->isError()) + return MainModule; + else + return nullptr; +} + +SourceFile *CompilerInstance::getInputFile() { + return Invocation.getInputFile(); +} + +void CompilerInstance::performCompilation() { + +} + +void CompilerInstance::performSema() { + +} + +void CompilerInstance::performParseOnly() { + Context = std::make_unique<ASTContext>(); + auto InputFile = Invocation.getInputFile(); + Parser P(*Context, SourceManager, *InputFile, Diag, InputFile->bufferID()); + MainModule = P.parseModule(); +} + +void CompilerInstance::freeContext() { + Context.reset(); +} + +void CompilerInstance::reset(CompilerInvocation &&I) { + Invocation = std::move(I); + MainModule = nullptr; + freeContext(); +} diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp new file mode 100644 index 0000000..3f2eebf --- /dev/null +++ b/lib/Frontend/CompilerInvocation.cpp @@ -0,0 +1,42 @@ +//===--- CompilerInvocation.cpp -------------------------------------------===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#include "dusk/Frontend/CompilerInvocation.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/Path.h" + +using namespace dusk; + +CompilerInvocation::CompilerInvocation() + : Target(llvm::sys::getDefaultTargetTriple()), OutputName("a.out") {} + +void CompilerInvocation::setArgs(SourceMgr &SM, DiagnosticEngine &Diag, + StringRef InFile, StringRef OutFile, + bool IsQ) { + OutputName = OutFile; + IsQuiet = IsQ; + + if (auto Err = llvm::MemoryBuffer::getFile(InFile)) { + auto Buff = std::move(*Err); + auto L = SMLoc::getFromPointer(Buff->getBufferStart()); + auto BuffPtr = Buff.get(); + auto BuffID = SM.AddNewSourceBuffer(std::move(Buff), L); + InputFile = std::make_unique<SourceFile>(BuffID, BuffPtr, InFile); + } else { + llvm_unreachable("Error opening or reading file"); + } +} diff --git a/lib/Frontend/Formatter.cpp b/lib/Frontend/Formatter.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/lib/Frontend/InputFile.cpp b/lib/Frontend/InputFile.cpp deleted file mode 100644 index f5567c0..0000000 --- a/lib/Frontend/InputFile.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "dusk/Frontend/InputFile.h" - -using namespace dusk; - -InputFile::InputFile(llvm::SourceMgr &SM, const StringRef F) - : Filename(F), SourceManager(SM) { - assert(!Filename.empty() && "Filename must not be an empty string."); - - if (auto Res = llvm::MemoryBuffer::getFile(Filename)) { - auto B = std::move(*Res); - auto L = SMLoc::getFromPointer(B->getBufferStart()); - Buffer = B.get(); - BufferID = SourceManager.AddNewSourceBuffer(std::move(B), L); - - } else { - assert("Error opening and/or reading file" && false); - } -} - - diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt index ed0c3df..7b5e659 100644 --- a/lib/IRGen/CMakeLists.txt +++ b/lib/IRGen/CMakeLists.txt @@ -8,8 +8,6 @@ set(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/GenStmt.h ${CMAKE_CURRENT_SOURCE_DIR}/IRGenerator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Scope.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/TopLevelExpr.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/TopLevelExpr.h ${SOURCE} PARENT_SCOPE ) diff --git a/lib/IRGen/TopLevelExpr.cpp b/lib/IRGen/TopLevelExpr.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/lib/IRGen/TopLevelExpr.h b/lib/IRGen/TopLevelExpr.h deleted file mode 100644 index e69de29..0000000 diff --git a/lib/Parser/ParseDecl.cpp b/lib/Parser/ParseDecl.cpp index 807d814..38b1e81 100644 --- a/lib/Parser/ParseDecl.cpp +++ b/lib/Parser/ParseDecl.cpp @@ -26,7 +26,7 @@ Decl *Parser::parseConstDecl() { return nullptr; } - return make<LetDecl>(ID.getText(), ID.getLoc(), L, parseDeclValue()); + return makeNode<LetDecl>(ID.getText(), ID.getLoc(), L, parseDeclValue()); } /// Var declaration @@ -44,7 +44,7 @@ Decl *Parser::parseVarDecl() { return nullptr; } - return make<VarDecl>(ID.getText(), ID.getLoc(), L, parseDeclValue()); + return makeNode<VarDecl>(ID.getText(), ID.getLoc(), L, parseDeclValue()); } /// DeclVal ::= @@ -82,7 +82,7 @@ Decl *Parser::parseFuncDecl() { auto Args = static_cast<VarPattern *>(parseVarPattern()); auto RetTy = parseFuncDeclType(); - return make<FuncDecl>(ID.getText(), ID.getLoc(), FL, Args, RetTy); + return makeNode<FuncDecl>(ID.getText(), ID.getLoc(), FL, Args, RetTy); } /// Function return type @@ -121,6 +121,6 @@ Decl *Parser::parseParamDecl() { auto ID = Tok; consumeToken(); - return make<ParamDecl>(ID.getText(), ID.getLoc()); + return makeNode<ParamDecl>(ID.getText(), ID.getLoc()); } diff --git a/lib/Parser/ParseExpr.cpp b/lib/Parser/ParseExpr.cpp index 8cfed77..e4bc62c 100644 --- a/lib/Parser/ParseExpr.cpp +++ b/lib/Parser/ParseExpr.cpp @@ -52,7 +52,7 @@ Expr *Parser::parseAssignExprRHS(Expr *LHS) { case tok::assign: consumeToken(); - return make<AssignExpr>((IdentifierExpr *)LHS, parseExpr()); + return makeNode<AssignExpr>((IdentifierExpr *)LHS, parseExpr()); default: diagnose(Tok.getLoc()); @@ -94,7 +94,7 @@ Expr *Parser::parseLogicalExprRHS(Expr *LHS) { case tok::greater: case tok::greater_eq: consumeToken(); - return make<InfixExpr>(LHS, parseArithExpr(), T); + return makeNode<InfixExpr>(LHS, parseArithExpr(), T); default: diagnose(Tok.getLoc()); @@ -138,7 +138,7 @@ Expr *Parser::parseArithExprRHS(Expr *LHS) { case tok::plus: case tok::minus: consumeToken(); - return make<InfixExpr>(LHS, parseExpr(), T); + return makeNode<InfixExpr>(LHS, parseExpr(), T); default: diagnose(Tok.getLoc()); @@ -185,7 +185,7 @@ Expr *Parser::parseMulExprRHS(Expr *LHS) { case tok::multipy: case tok::divide: consumeToken(); - return make<InfixExpr>(LHS, parseExpr(), T); + return makeNode<InfixExpr>(LHS, parseExpr(), T); default: diagnose(Tok.getLoc()); @@ -246,21 +246,21 @@ Expr *Parser::parseIdentifierExpr() { auto Name = Tok.getText(); auto Loc = consumeToken(); - return make<IdentifierExpr>(Name, Loc); + return makeNode<IdentifierExpr>(Name, Loc); } /// CallExpr ::= idenifier '(' Args ')' Expr *Parser::parseCallExpr(Expr *Dest) { // Validate `(` assert(Tok.is(tok::l_paren) && "Invalid parse method."); - return make<CallExpr>(Dest, parseExprPattern()); + return makeNode<CallExpr>(Dest, parseExprPattern()); } /// SubscriptExpr ::= idenifier '[' Args ']' Expr *Parser::parseSubscriptExpr(Expr *Dest) { // Validate `[` assert(Tok.is(tok::l_bracket) && "Invalid parse method."); - return make<SubscriptExpr>(Dest, parseSubscriptStmt()); + return makeNode<SubscriptExpr>(Dest, parseSubscriptStmt()); } /// PrimaryExpr ::= '(' Expr ')' @@ -274,7 +274,7 @@ Expr *Parser::parseParenExpr() { .fixItAfter(")", Tok.getLoc()); return nullptr; } - return make<ParenExpr>(E, L, PreviousLoc); + return makeNode<ParenExpr>(E, L, PreviousLoc); } Expr *Parser::parseUnaryExpr() { @@ -283,7 +283,7 @@ Expr *Parser::parseUnaryExpr() { auto Op = Tok; consumeToken(); - return make<PrefixExpr>(parsePrimaryExpr(), Op); + return makeNode<PrefixExpr>(parsePrimaryExpr(), Op); } /// Properly parse number literal @@ -317,5 +317,5 @@ Expr *Parser::parseNumberLiteralExpr() { } consumeToken(); - return make<NumberLiteralExpr>(Value, R); + return makeNode<NumberLiteralExpr>(Value, R); } diff --git a/lib/Parser/ParsePattern.cpp b/lib/Parser/ParsePattern.cpp index 376f944..d42e443 100644 --- a/lib/Parser/ParsePattern.cpp +++ b/lib/Parser/ParsePattern.cpp @@ -28,7 +28,7 @@ Pattern *Parser::parseExprPattern() { .fixItBefore(")", Tok.getLoc()); return nullptr; } - return make<ExprPattern>(std::move(C), LP, PreviousLoc); + return makePattern<ExprPattern>(std::move(C), LP, PreviousLoc); } /// ExprPatternBody ::= @@ -96,7 +96,7 @@ Pattern *Parser::parseVarPattern() { .fixItBefore(")", Tok.getLoc()); return nullptr; } - return make<VarPattern>(std::move(C), LP, PreviousLoc); + return makePattern<VarPattern>(std::move(C), LP, PreviousLoc); } /// VarPatternBody ::= diff --git a/lib/Parser/ParseStmt.cpp b/lib/Parser/ParseStmt.cpp index b134951..c631e32 100644 --- a/lib/Parser/ParseStmt.cpp +++ b/lib/Parser/ParseStmt.cpp @@ -51,7 +51,7 @@ Stmt *Parser::parseBreakStmt() { .fixItAfter(";", PreviousLoc); return nullptr; } - return make<BreakStmt>(llvm::SMRange{S, E}); + return makeNode<BreakStmt>(llvm::SMRange{S, E}); } /// ReturnStmt ::= @@ -78,7 +78,7 @@ Stmt *Parser::parseReturnStmt() { .fixItAfter(";", PreviousLoc); return nullptr; } - return make<ReturnStmt>(RL, E); + return makeNode<ReturnStmt>(RL, E); } /// SubscriptionPattern ::= @@ -95,7 +95,7 @@ Stmt *Parser::parseSubscriptStmt() { return nullptr; } - return make<SubscriptStmt>(V, L, PreviousLoc); + return makeNode<SubscriptStmt>(V, L, PreviousLoc); } /// Block ::= @@ -115,7 +115,7 @@ Stmt *Parser::parseBlock() { .fixItBefore("}", Tok.getLoc()); return nullptr; } - return make<BlockStmt>(L, PreviousLoc, std::move(Nodes)); + return makeNode<BlockStmt>(L, PreviousLoc, std::move(Nodes)); } ASTNode *Parser::parseBlockBody() { @@ -171,7 +171,7 @@ Stmt *Parser::parseExterStmt() { return nullptr; } - auto D = make<ExternStmt>(EL, parseFuncDecl()); + auto D = makeNode<ExternStmt>(EL, parseFuncDecl()); if (consumeIf(tok::semicolon)) return D; @@ -187,7 +187,7 @@ Stmt *Parser::parseFuncStmt() { assert(Tok.is(tok::kwFunc) && "Invalid parse method"); auto D = parseFuncDecl(); if (Tok.is(tok::l_brace)) - return make<FuncStmt>(D, parseBlock()); + return makeNode<FuncStmt>(D, parseBlock()); diagnose(Tok.getLoc(), diag::DiagID::expected_l_brace) .fixIt("{", Tok.getLoc()); @@ -216,7 +216,7 @@ Stmt *Parser::parseForStmt() { return nullptr; } auto Body = parseBlock(); - return make<ForStmt>(FLoc, Var, Rng, Body); + return makeNode<ForStmt>(FLoc, Var, Rng, Body); } Stmt *Parser::parseRangeStmt() { @@ -230,7 +230,7 @@ Stmt *Parser::parseRangeStmt() { } consumeToken(); auto E = parseExpr(); - return make<RangeStmt>(S, E, Op); + return makeNode<RangeStmt>(S, E, Op); } Stmt *Parser::parseWhileStmt() { @@ -239,7 +239,7 @@ Stmt *Parser::parseWhileStmt() { auto Cond = parseExpr(); auto Body = parseBlock(); - return make<WhileStmt>(L, Cond, Body); + return makeNode<WhileStmt>(L, Cond, Body); } Stmt *Parser::parseIfStmt() { @@ -248,7 +248,7 @@ Stmt *Parser::parseIfStmt() { auto Cond = parseExpr(); auto Then = parseBlock(); auto Else = parseElseStmt(); - return make<IfStmt>(L, Cond, Then, Else); + return makeNode<IfStmt>(L, Cond, Then, Else); } Stmt *Parser::parseElseStmt() { diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp index 42e6bd0..f6a1afa 100644 --- a/lib/Parser/Parser.cpp +++ b/lib/Parser/Parser.cpp @@ -17,10 +17,10 @@ using namespace dusk; // MARK: - Parser -Parser::Parser(llvm::SourceMgr &SM, InputFile &SF, DiagnosticEngine &Engine, - unsigned BufferID) - : SourceManager(SM), SourceFile(SF), Engine(Engine), - L(new Lexer(SM, BufferID, &Engine)) {} +Parser::Parser(ASTContext &C, llvm::SourceMgr &SM, SourceFile &SF, + DiagnosticEngine &Diag, unsigned BufferID) + : Context(C), SourceManager(SM), SF(SF), Diag(Diag), + L(new Lexer(SM, BufferID, &Diag)) {} Parser::~Parser() { delete L; } @@ -43,26 +43,25 @@ DiagnosticRef Parser::diagnose(SMLoc Loc, diag::DiagID ID) { if (diag::DiagID::unexpected_token == ID && R.isError()) // No better diagnostics than already given. return DiagnosticRef(); - R.setError(); + Context.setError(); if (Tok.is(tok::unknown)) // Handeled by lexer. return DiagnosticRef(); - return Engine.diagnose(Loc, ID); + return Diag.diagnose(Loc, ID); } // MARK: - Main parsing loop -ParserResult &&Parser::parse() { +ModuleDecl *Parser::parseModule() { std::vector<ASTNode *> Nodes; consumeToken(); while (Tok.isNot(tok::eof) && !R.isError()) Nodes.push_back(parseGlobal()); - - if (Nodes.size() != 0) - R.setRoot(make<ModuleDecl>(SourceFile.file(), std::move(Nodes))); - return std::move(R); + + return makeNode<ModuleDecl>(SF.file(), std::move(Nodes)); } + ASTNode *Parser::parseGlobal() { switch (Tok.getKind()) { case tok::kwVar: diff --git a/tools/dusk-format/main.cpp b/tools/dusk-format/main.cpp index 2e31454..cfcbbbc 100644 --- a/tools/dusk-format/main.cpp +++ b/tools/dusk-format/main.cpp @@ -1,14 +1,35 @@ -#include "dusk/Frontend/Compiler.h" +#include "dusk/Basic/LLVM.h" +#include "dusk/Frontend/CompilerInvocation.h" +#include "dusk/Frontend/CompilerInstance.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" #include <iostream> +#include <string> using namespace dusk; +using namespace llvm; + +cl::opt<std::string> InFile(cl::Positional, cl::Required, + cl::desc("<input file>"), cl::init("-")); + +cl::opt<std::string> OutFile("o", cl::desc("Specify output filename"), + cl::value_desc("<filename>")); +cl::opt<bool> IsQuiet("quiet", cl::desc("Suppress diagnostics")); +cl::alias IsQuiet2("q", cl::desc("Suppress diagnostics"), + cl::aliasopt(IsQuiet)); + +void initCompilerInstance(CompilerInstance &C) { + CompilerInvocation Inv; + Inv.setArgs(C.getSourceManager(), C.getDiags(), InFile, OutFile, IsQuiet); + C.reset(std::move(Inv)); +} int main(int argc, const char *argv[]) { - std::vector<llvm::StringRef> Filenames; - for (size_t i = 1; i < argc; i++) { - Filenames.push_back(argv[i]); - } - Compiler C(Filenames); - C.Compile(); + cl::ParseCommandLineOptions(argc, argv); + CompilerInstance Compiler; + initCompilerInstance(Compiler); + + Compiler.performParseOnly(); + return 0; } -- GitLab