Update the serene executable to use llvm::cl and spit out the AST
This commit is contained in:
parent
cd0989d060
commit
04a50eb65b
|
@ -7,6 +7,7 @@ project(Serene
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||||
|
|
||||||
# Only do these if this is the main project, and not if it is included through add_subdirectory
|
# Only do these if this is the main project, and not if it is included through add_subdirectory
|
||||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
|
|
||||||
|
@ -34,6 +35,8 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
set(MemoryCheckCommand "valgrind")
|
set(MemoryCheckCommand "valgrind")
|
||||||
|
|
||||||
|
add_compile_options(-fno-rtti)
|
||||||
|
|
||||||
configure_file(${INCLUDE_DIR}/config.h.in config.h)
|
configure_file(${INCLUDE_DIR}/config.h.in config.h)
|
||||||
|
|
||||||
# Let's nicely support folders in IDEs
|
# Let's nicely support folders in IDEs
|
||||||
|
@ -93,4 +96,5 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "serene/serene.hpp"
|
#include "serene/serene.hpp"
|
||||||
#include "serene/compiler.hpp"
|
#include "serene/compiler.hpp"
|
||||||
|
#include "serene/reader.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <llvm/Support/CommandLine.h>
|
#include <llvm/Support/CommandLine.h>
|
||||||
|
|
||||||
|
@ -33,27 +34,31 @@ using namespace serene;
|
||||||
namespace cl = llvm::cl;
|
namespace cl = llvm::cl;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
enum Action { None, DumpAST }
|
enum Action { None, DumpAST };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cl::opt<std::string> inputFile(cl::Positional,
|
||||||
|
cl::desc("The Serene file to compile"),
|
||||||
|
cl::init("-"),
|
||||||
|
cl::value_desc("filename"));
|
||||||
|
|
||||||
static cl::opt<enum Action>
|
static cl::opt<enum Action>
|
||||||
emitAction("emit", cl::desc("Select what to dump."),
|
emitAction("emit", cl::desc("Select what to dump."),
|
||||||
cl::values(clEnumValN(DumpAST, "ast", "Output the AST only")));
|
cl::values(clEnumValN(DumpAST, "ast", "Output the AST only")));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
cl::ParseCommandLineOptions(argc, argv, "Serene compiler \n");
|
cl::ParseCommandLineOptions(argc, argv, "Serene compiler \n");
|
||||||
|
|
||||||
|
|
||||||
switch (emitAction) {
|
switch (emitAction) {
|
||||||
case Action::DumpAST:
|
case Action::DumpAST: {
|
||||||
Reader r = Reader(input);
|
FileReader *r = new FileReader(inputFile);
|
||||||
r->dump();
|
r->dumpAST();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
llvm::errs() << "No action specified. TODO: Print out help here";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
string input_file(argv[1]);
|
|
||||||
|
|
||||||
Compiler c;
|
return 1;
|
||||||
c.compile(input_file);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
(println asd)
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ERROR_H
|
||||||
|
#define ERROR_H
|
||||||
|
|
||||||
|
#include "serene/compiler.hpp"
|
||||||
|
#include "serene/expr.hpp"
|
||||||
|
#include "serene/llvm/IR/Value.h"
|
||||||
|
#include "serene/state.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
class Error : public AExpr {
|
||||||
|
const std::string msg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Error(const std::string &msg) : msg(msg) {}
|
||||||
|
virtual ~Error();
|
||||||
|
|
||||||
|
const std::string &message() const;
|
||||||
|
|
||||||
|
ExprId id() const override { return error; }
|
||||||
|
std::string string_repr() const override;
|
||||||
|
std::string dumpAST() const override;
|
||||||
|
|
||||||
|
llvm::Value *codegen(Compiler &compiler, State &state) override;
|
||||||
|
};
|
||||||
|
} // namespace serene
|
||||||
|
|
||||||
|
#endif
|
|
@ -39,7 +39,8 @@
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
enum ExprId : unsigned char { aexpr = 0, symbol, list, def };
|
// TODO: Rename this enum and move it to a namespace
|
||||||
|
enum ExprId : unsigned char { aexpr = 0, symbol, list, def, error };
|
||||||
|
|
||||||
class AExpr {
|
class AExpr {
|
||||||
public:
|
public:
|
||||||
|
@ -48,6 +49,7 @@ public:
|
||||||
virtual ExprId id() const = 0;
|
virtual ExprId id() const = 0;
|
||||||
virtual std::string string_repr() const = 0;
|
virtual std::string string_repr() const = 0;
|
||||||
virtual llvm::Value *codegen(Compiler &compiler, State &state) = 0;
|
virtual llvm::Value *codegen(Compiler &compiler, State &state) = 0;
|
||||||
|
virtual std::string dumpAST() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ast_node = std::shared_ptr<AExpr>;
|
using ast_node = std::shared_ptr<AExpr>;
|
||||||
|
|
|
@ -38,6 +38,7 @@ class List : public AExpr {
|
||||||
public:
|
public:
|
||||||
ExprId id() const override { return list; }
|
ExprId id() const override { return list; }
|
||||||
|
|
||||||
|
std::string dumpAST() const override;
|
||||||
std::string string_repr() const override;
|
std::string string_repr() const override;
|
||||||
size_t length() const;
|
size_t length() const;
|
||||||
|
|
||||||
|
|
|
@ -72,11 +72,33 @@ private:
|
||||||
ast_node read_expr();
|
ast_node read_expr();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Reader(const std::string &);
|
Reader() : input_stream(""){};
|
||||||
|
Reader(const std::string);
|
||||||
|
|
||||||
|
void setInput(const std::string);
|
||||||
|
|
||||||
ast_tree &read();
|
ast_tree &read();
|
||||||
|
|
||||||
|
// Dumps the AST data to stdout
|
||||||
|
void dumpAST();
|
||||||
|
|
||||||
~Reader();
|
~Reader();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FileReader {
|
||||||
|
std::string file;
|
||||||
|
Reader *reader;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileReader(const std::string file_name)
|
||||||
|
: file(file_name), reader(new Reader()) {}
|
||||||
|
// Dumps the AST data to stdout
|
||||||
|
void dumpAST();
|
||||||
|
|
||||||
|
ast_tree &read();
|
||||||
|
|
||||||
|
~FileReader();
|
||||||
|
};
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
ExprId id() const override { return def; }
|
ExprId id() const override { return def; }
|
||||||
|
|
||||||
Def(serene::Symbol *symbol_, AExpr *value_);
|
Def(serene::Symbol *symbol_, AExpr *value_);
|
||||||
|
std::string dumpAST() const override;
|
||||||
std::string string_repr() const override;
|
std::string string_repr() const override;
|
||||||
llvm::Value *codegen(Compiler &compiler, State &state) override;
|
llvm::Value *codegen(Compiler &compiler, State &state) override;
|
||||||
static ast_node make(Compiler &compiler, State &state, const List *args);
|
static ast_node make(Compiler &compiler, State &state, const List *args);
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
|
|
||||||
ExprId id() const override { return symbol; }
|
ExprId id() const override { return symbol; }
|
||||||
std::string string_repr() const override;
|
std::string string_repr() const override;
|
||||||
|
std::string dumpAST() const override;
|
||||||
|
|
||||||
llvm::Value *codegen(Compiler &compiler, State &state) override;
|
llvm::Value *codegen(Compiler &compiler, State &state) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serene/error.hpp"
|
||||||
|
#include "serene/compiler.hpp"
|
||||||
|
#include "serene/expr.hpp"
|
||||||
|
#include "serene/llvm/IR/Value.h"
|
||||||
|
#include "serene/namespace.hpp"
|
||||||
|
#include "serene/state.hpp"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
#include <llvm/IR/Constants.h>
|
||||||
|
#include <llvm/IR/Type.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
|
||||||
|
string Error::string_repr() const { return fmt::format("Error: {}", msg); }
|
||||||
|
|
||||||
|
string Error::dumpAST() const { return fmt::format("<Error: {}>", this->msg); }
|
||||||
|
|
||||||
|
Value *Error::codegen(Compiler &compiler, State &state) { return nullptr; }
|
||||||
|
|
||||||
|
Error::~Error() { EXPR_LOG("Destroying Error"); }
|
||||||
|
} // namespace serene
|
40
src/list.cpp
40
src/list.cpp
|
@ -60,35 +60,17 @@ std::string List::string_repr() const {
|
||||||
return fmt::format("({})", s);
|
return fmt::format("({})", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string List::dumpAST() const {
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
for (auto &n : nodes_) {
|
||||||
|
s = fmt::format("{} {}", s, n->dumpAST());
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt::format("<List: {}>", s);
|
||||||
|
}
|
||||||
|
|
||||||
inline size_t List::length() const { return nodes_.size(); }
|
inline size_t List::length() const { return nodes_.size(); }
|
||||||
|
|
||||||
Value *List::codegen(Compiler &compiler, State &state) {
|
Value *List::codegen(Compiler &compiler, State &state) { return nullptr; }
|
||||||
if (length() == 0) {
|
|
||||||
compiler.log_error("Can't eveluate empty list.");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto def_ptr = at(0).value_or(nullptr);
|
|
||||||
auto name_ptr = at(1).value_or(nullptr);
|
|
||||||
auto body_ptr = at(2).value_or(nullptr);
|
|
||||||
|
|
||||||
if (def_ptr && def_ptr->id() == symbol &&
|
|
||||||
static_cast<Symbol *>(def_ptr.get())->name() == "def") {
|
|
||||||
|
|
||||||
if (!name_ptr && def_ptr->id() != symbol) {
|
|
||||||
return compiler.log_error("First argument of 'def' has to be a symbol.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!body_ptr) {
|
|
||||||
return compiler.log_error("'def' needs 3 arguments, two has been given.");
|
|
||||||
}
|
|
||||||
|
|
||||||
special_forms::Def def(static_cast<Symbol *>(name_ptr.get()),
|
|
||||||
body_ptr.get());
|
|
||||||
return def.codegen(compiler, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPR_LOG("Not implemented in list.");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -23,9 +23,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "serene/reader.hpp"
|
#include "serene/reader.hpp"
|
||||||
|
#include "serene/error.hpp"
|
||||||
#include "serene/list.hpp"
|
#include "serene/list.hpp"
|
||||||
#include "serene/symbol.hpp"
|
#include "serene/symbol.hpp"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -33,7 +35,9 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
Reader::Reader(const string &input) {
|
Reader::Reader(const string input) { this->setInput(input); };
|
||||||
|
|
||||||
|
void Reader::setInput(const string input) {
|
||||||
input_stream.write(input.c_str(), input.size());
|
input_stream.write(input.c_str(), input.size());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,5 +157,48 @@ ast_tree &Reader::read() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->ast;
|
return this->ast;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
void Reader::dumpAST() {
|
||||||
|
ast_tree &ast = this->read();
|
||||||
|
std::string result = "";
|
||||||
|
for (auto &node : ast) {
|
||||||
|
result = fmt::format("{0} {1}", result, node->dumpAST());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_tree &FileReader::read() {
|
||||||
|
std::string buffer;
|
||||||
|
|
||||||
|
std::ifstream f(file.c_str());
|
||||||
|
|
||||||
|
if (f) {
|
||||||
|
f.seekg(0, std::ios::end);
|
||||||
|
buffer.resize(f.tellg());
|
||||||
|
f.seekg(0);
|
||||||
|
f.read(buffer.data(), buffer.size());
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
reader->setInput(buffer);
|
||||||
|
|
||||||
|
return reader->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ReadError((char *)fmt::format("Can't find file '{}'", file).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileReader::dumpAST() {
|
||||||
|
ast_tree &ast = this->read();
|
||||||
|
std::string result = "";
|
||||||
|
for (auto &node : ast) {
|
||||||
|
result = fmt::format("{0} {1}", result, node->dumpAST());
|
||||||
|
}
|
||||||
|
cout << result << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileReader::~FileReader() {
|
||||||
|
delete this->reader;
|
||||||
|
READER_LOG("Destroying the file reader");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -72,6 +72,8 @@ string Def::string_repr() const {
|
||||||
return "Def";
|
return "Def";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string Def::dumpAST() const { return "<Def>"; }
|
||||||
|
|
||||||
Value *Def::codegen(Compiler &compiler, State &state) {
|
Value *Def::codegen(Compiler &compiler, State &state) {
|
||||||
state.set_in_current_ns_root_scope(m_sym->name(),
|
state.set_in_current_ns_root_scope(m_sym->name(),
|
||||||
m_value->codegen(compiler, state));
|
m_value->codegen(compiler, state));
|
||||||
|
|
|
@ -41,6 +41,10 @@ namespace serene {
|
||||||
|
|
||||||
string Symbol::string_repr() const { return name_; }
|
string Symbol::string_repr() const { return name_; }
|
||||||
|
|
||||||
|
string Symbol::dumpAST() const {
|
||||||
|
return fmt::format("<Symbol: {}>", this->name());
|
||||||
|
}
|
||||||
|
|
||||||
const string &Symbol::name() const { return name_; }
|
const string &Symbol::name() const { return name_; }
|
||||||
|
|
||||||
Symbol::Symbol(const string &name) : name_(name) {}
|
Symbol::Symbol(const string &name) : name_(name) {}
|
||||||
|
|
Loading…
Reference in New Issue