Create a very basic compiler setup to wire everything in the most basic way
This commit is contained in:
parent
6e36ce1711
commit
b27611d5ba
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue