Create a very basic compiler setup to wire everything in the most basic way

This commit is contained in:
Sameer Rahmani 2020-07-25 18:59:00 +01:00
parent 6e36ce1711
commit b27611d5ba
6 changed files with 106 additions and 18 deletions

View File

@ -23,7 +23,7 @@
*/
#include "serene/serene.hpp"
#include "serene/reader.hpp"
#include "serene/compiler.hpp"
#include <iostream>
using namespace std;
@ -33,13 +33,10 @@ int main(int argc, char *argv[]) {
UNUSED(argc);
cout << "Serene >>" << endl;
char *input_file = argv[1];
Reader *r = new Reader(input_file);
ast_tree &ast = r->read();
string input_file(argv[1]);
for (const ast_node &x : ast) {
cout << x->string_repr() << " ";
}
delete r;
Compiler *c{new Compiler()};
c->compile(input_file);
delete c;
return 0;
}

View File

@ -44,8 +44,9 @@ private:
std::map<std::string, llvm::Value *> scope;
public:
Namespace();
std::string name;
Namespace(std::string &n) : name(n){};
llvm::Value *lookup(std::string &name);
~Namespace();
};

View File

@ -31,14 +31,25 @@
#include <llvm/IR/Module.h>
#include <string>
#if defined(ENABLE_LOG) || defined(ENABLE_STATE_LOG)
#define STATE_LOG(...) __LOG("STATE", __VA_ARGS__);
#else
#define STATE_LOG(...) ;
#endif
namespace serene {
class State {
public:
std::map<std::string, Namespace *> namespaces;
Namespace *current_ns;
State() : namespaces(), current_ns(nullptr){};
void set_current_ns(Namespace *ns);
State();
void add_namespace(Namespace *ns, bool set_current, bool overwrite);
bool set_current_ns(Namespace *ns);
llvm::Value *lookup_in_current_scope(std::string &name);
~State();
};
} // namespace serene

View File

@ -24,6 +24,7 @@
#include "serene/compiler.hpp"
#include "serene/llvm/IR/Value.h"
#include "serene/namespace.hpp"
#include "serene/reader.hpp"
#include "serene/state.hpp"
#include <llvm/IR/IRBuilder.h>
@ -36,10 +37,18 @@ using namespace llvm;
namespace serene {
Compiler::Compiler() { builder = new IRBuilder(this->context); };
Compiler::Compiler() {
string default_ns_name("user");
Namespace *default_ns = new Namespace(default_ns_name);
builder = new IRBuilder(this->context);
state = new State();
state->add_namespace(default_ns, true, true);
};
Value *Compiler::log_error(const char *s) {
fmt::print("[Error]: {}", s);
fmt::print("[Error]: {}\n", s);
return nullptr;
};
@ -47,8 +56,10 @@ void Compiler::compile(string &input) {
Reader *r = new Reader(input);
ast_tree &ast = r->read();
COMPILER_LOG("Parsing the input has been done.")
for (const ast_node &x : ast) {
auto *IR = x->codegen(*this, *this->state);
auto *IR{x->codegen(*this, *this->state)};
if (IR) {
fmt::print("'{}' generates: \n", x->string_repr()
@ -56,10 +67,19 @@ void Compiler::compile(string &input) {
IR->print(errs());
fmt::print("\n");
} else {
fmt::print("No gen\n");
}
}
delete r;
COMPILER_LOG("Done!")
return;
};
Compiler::~Compiler() { delete this->builder; }
Compiler::~Compiler() {
COMPILER_LOG("Deleting state...");
delete state;
COMPILER_LOG("Deleting builder...");
delete builder;
}
} // namespace serene

View File

@ -32,5 +32,62 @@ using namespace std;
using namespace llvm;
namespace serene {
void State::set_current_ns(Namespace *ns) { current_ns = ns; };
State::State() { current_ns = nullptr; };
void State::add_namespace(Namespace *ns, bool set_current, bool overwrite) {
if (ns->name.empty()) {
// TODO: Better error handling
fmt::print("Error: namespace name is missing\n.");
exit(1);
}
Namespace *already_exist_ns = namespaces[ns->name];
if (already_exist_ns && !overwrite) {
return;
}
if (already_exist_ns) {
delete namespaces[ns->name];
}
namespaces[ns->name] = ns;
if (set_current) {
set_current_ns(ns);
}
};
bool State::set_current_ns(Namespace *ns) {
Namespace *already_exist_ns = namespaces[ns->name];
if (already_exist_ns) {
current_ns = ns;
return true;
}
return false;
};
Value *State::lookup_in_current_scope(string &name) {
if (this->current_ns) {
return current_ns->lookup(name);
}
fmt::print("FATAL ERROR: Current ns is not set.");
// TODO: Come up with the ERRNO table and return the proper ERRNO
exit(1);
};
State::~State() {
STATE_LOG("Deleting namespaces...")
std::map<string, Namespace *>::iterator it = namespaces.begin();
while (it != namespaces.end()) {
STATE_LOG("DELETING {}", it->first);
Namespace *tmp = it->second;
namespaces[it->first] = nullptr;
delete tmp;
it++;
}
STATE_LOG("Clearing namespaces...");
namespaces.clear();
};
} // namespace serene

View File

@ -28,6 +28,7 @@
#include "serene/llvm/IR/Value.h"
#include "serene/namespace.hpp"
#include "serene/state.hpp"
#include <assert.h>
#include <fmt/core.h>
#include <string>
@ -38,10 +39,11 @@ namespace serene {
string Symbol::string_repr() { return name; };
Value *Symbol::codegen(Compiler &compiler, State &state) {
Value *V = state.current_ns->lookup(name);
Value *V = state.lookup_in_current_scope(name);
if (!V) {
return compiler.log_error("Unknown symbol name");
return compiler.log_error(
fmt::format("Unable to resolve symbol '{}'.", name).c_str());
}
return V;
};