diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 0c39d4d63cfbb419495eea85f18444602271fc6b..2cbe7c746ea387bf78d637d3c7d050647298538e 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 0000000000000000000000000000000000000000..caf17fd5387920705aaa4b64c98c41396f229ee9 --- /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 af8db936d18d61ead248cfdcfb647039635e82ee..0bd1a5da5dbc08513021e7ce11e3ddbf2df0401f 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 98d812f94334b8167b9dae7a97d8062862ba9798..7321e37a04de4bbf12bccb53fe5de88eeb7638d3 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 4ab8409e9f258f820bb1b5d8175e60d674a31a80..4499d99e363b4c3f7fe3bf55027246746fd4fb1d 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 1d0d2a951b31c4145c71026333885793742c1cbf..a2122f58def6a558a89d31c403e2c9769cad75ad 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 63b3453715eb2e9452b16c906be731f2af457446..154c1fdf3c009c4d198e6f773abb2c806c654261 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 57d4cadbd4932c68940034e7c695f04b5a29e9d1..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..41af8816778e5b8dede9b22b3a6fc0d402a832df --- /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 0000000000000000000000000000000000000000..777081d2ddbf794ad659771f72078b67745570a2 --- /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 d84b670141e7136f0d804702e5539a38cfc3439f..20c474f7fb104dfc16ad9e85dc625f25d615a7a6 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 8428099c35dcd9be945d82d5240e3a7a97f53e92..8e1399e1e3914c7702e9b6d3cd7fb2ea68366bf6 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 22ea10bb119366c5c10343ad9ca057a202f1ebbd..42023b402ee6142532e96f76c2ffce688d658a23 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 2bf63462e0f127f56ac17e13524c1a31a6c1ae63..201dd44c4c468e181fb5e0f264ef46c2e79478bf 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 450cd4d2094ccf2a6e696c4c14bd32b4027f81d7..d7cf88a91334f6c9273d2e4d4399c5d342d57c93 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 04705cb6bc705da109c266ccfbe61d103ce08522..9164a5931664b20976d40b2423124c3b352ad8c1 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 18b7851df1bb2cc18b1deea108a4be74df29e37f..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..8cdd1303c85c82641bc1d768fb95e21e307bfbe2 --- /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 0000000000000000000000000000000000000000..3f2eebfa13ee358ffac01db1cf3b98cb82d460b1 --- /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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/lib/Frontend/InputFile.cpp b/lib/Frontend/InputFile.cpp deleted file mode 100644 index f5567c08ba2b2171beb4b02ddbb5e52f60e2cb63..0000000000000000000000000000000000000000 --- 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 ed0c3dfa80196072266c41d9c8abd6510550a1d8..7b5e659eac0842005106c41f1de3ff7b97f070ee 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/lib/IRGen/TopLevelExpr.h b/lib/IRGen/TopLevelExpr.h deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/lib/Parser/ParseDecl.cpp b/lib/Parser/ParseDecl.cpp index 807d8144671545eb4c0ee4077fc2d2c37f7ad726..38b1e819381613a35ecfb551acd31fe946fa3f7a 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 8cfed77cf87f27bf561a4bafbff850d879ca445c..e4bc62ccacaf2a1005a69c41d80e0e4b8de48d61 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 376f944477079872d847566f4f1de1dd1f203816..d42e44316437b84bbad307ba4892b9049bb9a00e 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 b1349512ab05df261ca5d8a223864dfcf3747c76..c631e326f49964035f8d15d52f3152fdf1e25ee9 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 42e6bd07db7c7d0a90ca27a237699f8f485482ea..f6a1afa60403ea51e39cf8d7bce80c702251ec5d 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 2e31454aab124a76e72a00e5d479e8c78eb2622c..cfcbbbcbe341a9233c8813915a6d3364ac0a8a29 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; }