Fix some of the hints from the 1on1 session on the refactoring the code
This commit is contained in:
parent
18910a4a2c
commit
dfa64e8f26
|
@ -35,8 +35,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
string input_file(argv[1]);
|
string input_file(argv[1]);
|
||||||
|
|
||||||
Compiler *c{new Compiler()};
|
Compiler c;
|
||||||
c->compile(input_file);
|
c.compile(input_file);
|
||||||
delete c;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/logger.hpp"
|
#include "serene/logger.hpp"
|
||||||
|
#include "serene/state.hpp"
|
||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
#include <llvm/IR/LLVMContext.h>
|
#include <llvm/IR/LLVMContext.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -38,18 +39,16 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
// Forward declaration of State. The actual declaration is in state.hpp
|
|
||||||
class State;
|
|
||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
llvm::LLVMContext context;
|
llvm::LLVMContext context;
|
||||||
llvm::IRBuilder<> *builder;
|
llvm::IRBuilder<> builder;
|
||||||
|
|
||||||
Compiler();
|
Compiler();
|
||||||
|
|
||||||
State *state;
|
State state;
|
||||||
llvm::Value *log_error(const char *s);
|
llvm::Value *log_error(const char *s);
|
||||||
void compile(std::string &input);
|
void compile(std::string &input);
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#ifndef NAMESPACE_H
|
#ifndef NAMESPACE_H
|
||||||
#define NAMESPACE_H
|
#define NAMESPACE_H
|
||||||
|
|
||||||
#include "serene/compiler.hpp"
|
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/logger.hpp"
|
#include "serene/logger.hpp"
|
||||||
#include <llvm/IR/Module.h>
|
#include <llvm/IR/Module.h>
|
||||||
|
@ -47,8 +46,8 @@ public:
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
Namespace(std::string &n) : name(n){};
|
Namespace(std::string &n) : name(n){};
|
||||||
llvm::Value *lookup(std::string &name);
|
llvm::Value *lookup(const std::string &name);
|
||||||
void insert_symbol(std::string &name, llvm::Value *v);
|
void insert_symbol(const std::string &name, llvm::Value *v);
|
||||||
|
|
||||||
void print_scope();
|
void print_scope();
|
||||||
~Namespace();
|
~Namespace();
|
||||||
|
|
|
@ -60,15 +60,15 @@ class Reader {
|
||||||
private:
|
private:
|
||||||
std::stringstream input_stream;
|
std::stringstream input_stream;
|
||||||
|
|
||||||
char get_char(bool);
|
char get_char(bool skip_whitespace);
|
||||||
void unget_char();
|
void unget_char();
|
||||||
bool is_valid_for_identifier(char);
|
bool is_valid_for_identifier(char c);
|
||||||
|
|
||||||
// The property to store the ast tree
|
// The property to store the ast tree
|
||||||
ast_tree ast;
|
ast_tree ast;
|
||||||
|
|
||||||
ast_node read_symbol();
|
ast_node read_symbol();
|
||||||
ast_list_node read_list(List *);
|
ast_list_node read_list(List *list);
|
||||||
ast_node read_expr();
|
ast_node read_expr();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
|
|
||||||
#include "serene/compiler.hpp"
|
#include "serene/compiler.hpp"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/expr.hpp"
|
||||||
#include "serene/list.hpp"
|
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/logger.hpp"
|
#include "serene/logger.hpp"
|
||||||
#include "serene/state.hpp"
|
#include "serene/state.hpp"
|
||||||
|
#include "serene/symbol.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#if defined(ENABLE_LOG) || defined(ENABLE_DEF_LOG)
|
#if defined(ENABLE_LOG) || defined(ENABLE_DEF_LOG)
|
||||||
|
@ -44,13 +44,13 @@ namespace special_forms {
|
||||||
|
|
||||||
class Def : public AExpr {
|
class Def : public AExpr {
|
||||||
private:
|
private:
|
||||||
AExpr *sym;
|
Symbol *m_sym;
|
||||||
AExpr *value;
|
AExpr *m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExprId id() const override { return def; };
|
ExprId id() const override { return def; }
|
||||||
|
|
||||||
Def(AExpr *s, AExpr *v);
|
Def(serene::Symbol *symbol_, AExpr *value_);
|
||||||
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;
|
||||||
~Def();
|
~Def();
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
void add_namespace(Namespace *ns, bool set_current, bool overwrite);
|
void add_namespace(Namespace *ns, bool set_current, bool overwrite);
|
||||||
bool set_current_ns(Namespace *ns);
|
bool set_current_ns(Namespace *ns);
|
||||||
llvm::Value *lookup_in_current_scope(std::string &name);
|
llvm::Value *lookup_in_current_scope(const std::string &name);
|
||||||
void set_in_current_ns_root_scope(std::string name, llvm::Value *v);
|
void set_in_current_ns_root_scope(std::string name, llvm::Value *v);
|
||||||
~State();
|
~State();
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,14 +37,11 @@ using namespace llvm;
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
Compiler::Compiler() {
|
Compiler::Compiler() : builder(context) {
|
||||||
string default_ns_name("user");
|
string default_ns_name("user");
|
||||||
Namespace *default_ns = new Namespace(default_ns_name);
|
Namespace *default_ns = new Namespace(default_ns_name);
|
||||||
|
|
||||||
builder = new IRBuilder(this->context);
|
state.add_namespace(default_ns, true, true);
|
||||||
state = new State();
|
|
||||||
|
|
||||||
state->add_namespace(default_ns, true, true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Value *Compiler::log_error(const char *s) {
|
Value *Compiler::log_error(const char *s) {
|
||||||
|
@ -58,7 +55,7 @@ void Compiler::compile(string &input) {
|
||||||
|
|
||||||
COMPILER_LOG("Parsing the input has been done.")
|
COMPILER_LOG("Parsing the input has been done.")
|
||||||
for (const ast_node &x : ast) {
|
for (const ast_node &x : ast) {
|
||||||
auto *IR{x->codegen(*this, *this->state)};
|
auto *IR{x->codegen(*this, this->state)};
|
||||||
|
|
||||||
if (IR) {
|
if (IR) {
|
||||||
fmt::print("'{}' generates: \n", x->string_repr()
|
fmt::print("'{}' generates: \n", x->string_repr()
|
||||||
|
@ -70,17 +67,12 @@ void Compiler::compile(string &input) {
|
||||||
fmt::print("No gen\n");
|
fmt::print("No gen\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state->current_ns->print_scope();
|
state.current_ns->print_scope();
|
||||||
delete r;
|
delete r;
|
||||||
COMPILER_LOG("Done!")
|
COMPILER_LOG("Done!")
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
Compiler::~Compiler() {
|
Compiler::~Compiler() { COMPILER_LOG("destroying"); }
|
||||||
COMPILER_LOG("Deleting state...");
|
|
||||||
delete state;
|
|
||||||
COMPILER_LOG("Deleting builder...");
|
|
||||||
delete builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
35
src/list.cpp
35
src/list.cpp
|
@ -36,22 +36,26 @@ using namespace llvm;
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
std::optional<ast_node> List::at(uint index) {
|
std::optional<ast_node> List::at(uint index) {
|
||||||
if (index >= nodes_.size())
|
if (index >= nodes_.size()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
auto itr = cbegin(nodes_);
|
auto itr = cbegin(nodes_);
|
||||||
std::advance(itr, index);
|
std::advance(itr, index);
|
||||||
return std::make_optional(*itr);
|
return std::make_optional(*itr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::cons(ast_node f) { nodes_.push_back(std::move(f)); }
|
void List::cons(ast_node node) { nodes_.push_front(std::move(node)); }
|
||||||
|
|
||||||
void List::append(ast_node t) { nodes_.push_front(std::move(t)); }
|
void List::append(ast_node node) { nodes_.push_back(std::move(node)); }
|
||||||
|
|
||||||
std::string List::string_repr() const {
|
std::string List::string_repr() const {
|
||||||
std::string s;
|
std::string s;
|
||||||
|
|
||||||
for (auto &n : nodes_)
|
for (auto &n : nodes_) {
|
||||||
s += n->string_repr();
|
// TODO: Fix the tailing space for the last element
|
||||||
|
s = s + n->string_repr() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
return fmt::format("({})", s);
|
return fmt::format("({})", s);
|
||||||
}
|
}
|
||||||
|
@ -68,16 +72,23 @@ Value *List::codegen(Compiler &compiler, State &state) {
|
||||||
auto name_ptr = at(1).value_or(nullptr);
|
auto name_ptr = at(1).value_or(nullptr);
|
||||||
auto body_ptr = at(2).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 (def_ptr && def_ptr->id() == symbol &&
|
||||||
return nullptr;
|
static_cast<Symbol *>(def_ptr.get())->name() == "def") {
|
||||||
|
|
||||||
if (!name_ptr && def_ptr->id() != symbol)
|
if (!name_ptr && def_ptr->id() != symbol) {
|
||||||
return nullptr;
|
return compiler.log_error("First argument of 'def' has to be a symbol.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!body_ptr)
|
if (!body_ptr) {
|
||||||
return nullptr;
|
return compiler.log_error("'def' needs 3 arguments, two has been given.");
|
||||||
|
}
|
||||||
|
|
||||||
special_forms::Def def(name_ptr.get(), body_ptr.get());
|
special_forms::Def def(static_cast<Symbol *>(name_ptr.get()),
|
||||||
|
body_ptr.get());
|
||||||
return def.codegen(compiler, state);
|
return def.codegen(compiler, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPR_LOG("Not implemented in list.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -32,8 +32,10 @@ using namespace llvm;
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
Value *Namespace::lookup(string &name) { return scope[name]; };
|
Value *Namespace::lookup(const string &name) { return scope[name]; };
|
||||||
void Namespace::insert_symbol(string &name, Value *v) { scope[name] = v; }
|
|
||||||
|
void Namespace::insert_symbol(const string &name, Value *v) { scope[name] = v; }
|
||||||
|
|
||||||
void Namespace::print_scope() {
|
void Namespace::print_scope() {
|
||||||
typedef map<string, Value *>::const_iterator Iter;
|
typedef map<string, Value *>::const_iterator Iter;
|
||||||
|
|
||||||
|
|
|
@ -38,27 +38,21 @@ using namespace llvm;
|
||||||
namespace serene {
|
namespace serene {
|
||||||
namespace special_forms {
|
namespace special_forms {
|
||||||
|
|
||||||
|
Def::Def(Symbol *symbol_, AExpr *value_) : m_sym(symbol_), m_value(value_) {}
|
||||||
Def::Def(AExpr *s, AExpr *v)
|
|
||||||
: sym(s), value(v) {
|
|
||||||
}
|
|
||||||
|
|
||||||
string Def::string_repr() const {
|
string Def::string_repr() const {
|
||||||
// this method is not going to get called.
|
// this method is not going to get called.
|
||||||
return "Def";
|
return "Def";
|
||||||
};
|
|
||||||
|
|
||||||
Value *Def::codegen(Compiler &compiler, State &state) {
|
|
||||||
|
|
||||||
auto symobj = dynamic_cast<Symbol *>(this->sym);
|
|
||||||
|
|
||||||
if (symobj->id() != symbol) {
|
|
||||||
return compiler.log_error("First argument of 'def' should be a symbol.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.set_in_current_ns_root_scope(symobj->name(), value->codegen(compiler, state));
|
Value *Def::codegen(Compiler &compiler, State &state) {
|
||||||
return symobj->codegen(compiler, state);
|
state.set_in_current_ns_root_scope(m_sym->name(),
|
||||||
};
|
m_value->codegen(compiler, state));
|
||||||
|
|
||||||
|
// TODO: Do we need to return the codegen of the symbol instead
|
||||||
|
// of the symbol itself?
|
||||||
|
return m_sym->codegen(compiler, state);
|
||||||
|
}
|
||||||
|
|
||||||
Def::~Def() { EXPR_LOG("Destroying def"); };
|
Def::~Def() { EXPR_LOG("Destroying def"); };
|
||||||
} // namespace special_forms
|
} // namespace special_forms
|
||||||
|
|
|
@ -67,7 +67,7 @@ bool State::set_current_ns(Namespace *ns) {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Value *State::lookup_in_current_scope(string &name) {
|
Value *State::lookup_in_current_scope(const string &name) {
|
||||||
if (current_ns) {
|
if (current_ns) {
|
||||||
return current_ns->lookup(name);
|
return current_ns->lookup(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,21 +46,19 @@ const string &Symbol::name() const { return name_; }
|
||||||
Symbol::Symbol(const string &name) : name_(name) {}
|
Symbol::Symbol(const string &name) : name_(name) {}
|
||||||
|
|
||||||
Value *Symbol::codegen(Compiler &compiler, State &state) {
|
Value *Symbol::codegen(Compiler &compiler, State &state) {
|
||||||
auto name = this->name_;
|
if (name() == "false") {
|
||||||
|
|
||||||
if (name == "false") {
|
|
||||||
return ConstantInt::get(Type::getInt1Ty(compiler.context), 0);
|
return ConstantInt::get(Type::getInt1Ty(compiler.context), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == "true") {
|
if (name() == "true") {
|
||||||
return ConstantInt::get(Type::getInt1Ty(compiler.context), 1);
|
return ConstantInt::get(Type::getInt1Ty(compiler.context), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *V = state.lookup_in_current_scope(name);
|
Value *V = state.lookup_in_current_scope(name());
|
||||||
|
|
||||||
if (!V) {
|
if (!V) {
|
||||||
return compiler.log_error(
|
return compiler.log_error(
|
||||||
fmt::format("Unable to resolve symbol '{}'.", name).c_str());
|
fmt::format("Unable to resolve symbol '{}'.", name()).c_str());
|
||||||
}
|
}
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue