Compare commits

..

No commits in common. "6b5f7e25b7326c84257a082ed9535d1f3dcb5742" and "7f8dae74ac6f5580aa9e3243fe85a8dd0a43014a" have entirely different histories.

12 changed files with 166 additions and 392 deletions

View File

@ -32,7 +32,6 @@ add_executable(compiler
binop.cpp binop.hpp
instruction.cpp instruction.hpp
graph.cpp graph.hpp
global_scope.cpp global_scope.hpp
${BISON_parser_OUTPUTS}
${FLEX_scanner_OUTPUTS}
main.cpp

View File

@ -3,7 +3,6 @@
#include "binop.hpp"
#include "error.hpp"
#include "type_env.hpp"
#include "env.hpp"
static void print_indent(int n, std::ostream& to) {
while(n--) to << " ";
@ -14,17 +13,12 @@ void ast_int::print(int indent, std::ostream& to) const {
to << "INT: " << value << std::endl;
}
void ast_int::find_free(std::set<std::string>& into) {
}
type_ptr ast_int::typecheck(type_mgr& mgr, type_env_ptr& env) {
void ast_int::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = env;
return type_ptr(new type_app(env->lookup_type("Int")));
}
void ast_int::translate(global_scope& scope) {
type_ptr ast_int::typecheck(type_mgr& mgr) {
return type_ptr(new type_app(env->lookup_type("Int")));
}
void ast_int::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
@ -36,24 +30,20 @@ void ast_lid::print(int indent, std::ostream& to) const {
to << "LID: " << id << std::endl;
}
void ast_lid::find_free(std::set<std::string>& into) {
into.insert(id);
}
type_ptr ast_lid::typecheck(type_mgr& mgr, type_env_ptr& env) {
void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = env;
return env->lookup(id)->instantiate(mgr);
if(env->lookup(id) == nullptr) into.insert(id);
}
void ast_lid::translate(global_scope& scope) {
type_ptr ast_lid::typecheck(type_mgr& mgr) {
return env->lookup(id)->instantiate(mgr);
}
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(
(env->has_variable(id) && !this->env->is_global(id)) ?
env->has_variable(id) ?
(instruction*) new instruction_push(env->get_offset(id)) :
(instruction*) new instruction_pushglobal(this->env->get_mangled_name(id))));
(instruction*) new instruction_pushglobal(id)));
}
void ast_uid::print(int indent, std::ostream& to) const {
@ -61,22 +51,16 @@ void ast_uid::print(int indent, std::ostream& to) const {
to << "UID: " << id << std::endl;
}
void ast_uid::find_free(std::set<std::string>& into) {
void ast_uid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = env;
}
type_ptr ast_uid::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
type_ptr ast_uid::typecheck(type_mgr& mgr) {
return env->lookup(id)->instantiate(mgr);
}
void ast_uid::translate(global_scope& scope) {
}
void ast_uid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(
new instruction_pushglobal(this->env->get_mangled_name(id))));
into.push_back(instruction_ptr(new instruction_pushglobal(id)));
}
void ast_binop::print(int indent, std::ostream& to) const {
@ -86,15 +70,15 @@ void ast_binop::print(int indent, std::ostream& to) const {
right->print(indent + 1, to);
}
void ast_binop::find_free(std::set<std::string>& into) {
left->find_free(into);
right->find_free(into);
void ast_binop::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = env;
left->find_free(mgr, env, into);
right->find_free(mgr, env, into);
}
type_ptr ast_binop::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
type_ptr ltype = left->typecheck(mgr, env);
type_ptr rtype = right->typecheck(mgr, env);
type_ptr ast_binop::typecheck(type_mgr& mgr) {
type_ptr ltype = left->typecheck(mgr);
type_ptr rtype = right->typecheck(mgr);
type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr);
if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op));
@ -106,11 +90,6 @@ type_ptr ast_binop::typecheck(type_mgr& mgr, type_env_ptr& env) {
return return_type;
}
void ast_binop::translate(global_scope& scope) {
left->translate(scope);
right->translate(scope);
}
void ast_binop::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
right->compile(env, into);
left->compile(env_ptr(new env_offset(1, env)), into);
@ -127,15 +106,15 @@ void ast_app::print(int indent, std::ostream& to) const {
right->print(indent + 1, to);
}
void ast_app::find_free(std::set<std::string>& into) {
left->find_free(into);
right->find_free(into);
void ast_app::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = env;
left->find_free(mgr, env, into);
right->find_free(mgr, env, into);
}
type_ptr ast_app::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
type_ptr ltype = left->typecheck(mgr, env);
type_ptr rtype = right->typecheck(mgr, env);
type_ptr ast_app::typecheck(type_mgr& mgr) {
type_ptr ltype = left->typecheck(mgr);
type_ptr rtype = right->typecheck(mgr);
type_ptr return_type = mgr.new_type();
type_ptr arrow = type_ptr(new type_arr(rtype, return_type));
@ -143,11 +122,6 @@ type_ptr ast_app::typecheck(type_mgr& mgr, type_env_ptr& env) {
return return_type;
}
void ast_app::translate(global_scope& scope) {
left->translate(scope);
right->translate(scope);
}
void ast_app::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
right->compile(env, into);
left->compile(env_ptr(new env_offset(1, env)), into);
@ -165,30 +139,24 @@ void ast_case::print(int indent, std::ostream& to) const {
}
}
void ast_case::find_free(std::set<std::string>& into) {
of->find_free(into);
void ast_case::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = env;
of->find_free(mgr, env, into);
for(auto& branch : branches) {
std::set<std::string> free_in_branch;
std::set<std::string> pattern_variables;
branch->pat->find_variables(pattern_variables);
branch->expr->find_free(free_in_branch);
for(auto& free : free_in_branch) {
if(pattern_variables.find(free) == pattern_variables.end())
into.insert(free);
}
type_env_ptr new_env = type_scope(env);
branch->pat->insert_bindings(mgr, new_env);
branch->expr->find_free(mgr, new_env, into);
}
}
type_ptr ast_case::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
type_ptr ast_case::typecheck(type_mgr& mgr) {
type_var* var;
type_ptr case_type = mgr.resolve(of->typecheck(mgr, env), var);
type_ptr case_type = mgr.resolve(of->typecheck(mgr), var);
type_ptr branch_type = mgr.new_type();
for(auto& branch : branches) {
type_env_ptr new_env = type_scope(env);
branch->pat->typecheck(case_type, mgr, new_env);
type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env);
branch->pat->typecheck(case_type, mgr, branch->expr->env);
type_ptr curr_branch_type = branch->expr->typecheck(mgr);
mgr.unify(branch_type, curr_branch_type);
}
@ -202,13 +170,6 @@ type_ptr ast_case::typecheck(type_mgr& mgr, type_env_ptr& env) {
return branch_type;
}
void ast_case::translate(global_scope& scope) {
of->translate(scope);
for(auto& branch : branches) {
branch->expr->translate(scope);
}
}
void ast_case::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
type_app* app_type = dynamic_cast<type_app*>(input_type.get());
type_data* type = dynamic_cast<type_data*>(app_type->constructor.get());
@ -271,75 +232,36 @@ void ast_let::print(int indent, std::ostream& to) const {
in->print(indent + 1, to);
}
void ast_let::find_free(std::set<std::string>& into) {
definitions.find_free(into);
void ast_let::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = env;
definitions.find_free(mgr, env, into);
std::set<std::string> all_free;
in->find_free(all_free);
in->find_free(mgr, definitions.env, all_free);
for(auto& free_var : all_free) {
if(definitions.defs_defn.find(free_var) == definitions.defs_defn.end())
into.insert(free_var);
}
}
type_ptr ast_let::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
definitions.typecheck(mgr, env);
return in->typecheck(mgr, definitions.env);
}
void ast_let::translate(global_scope& scope) {
for(auto& def : definitions.defs_data) {
def.second->into_globals(scope);
}
for(auto& def : definitions.defs_defn) {
size_t original_params = def.second->params.size();
std::string original_name = def.second->name;
auto& global_definition = def.second->into_global(scope);
size_t captured = global_definition.params.size() - original_params;
type_env_ptr mangled_env = type_scope(env);
mangled_env->bind(def.first, env->lookup(def.first), visibility::global);
mangled_env->set_mangled_name(def.first, global_definition.name);
ast_ptr global_app(new ast_lid(global_definition.name));
global_app->env = mangled_env;
for(auto& param : global_definition.params) {
if(!(captured--)) break;
ast_ptr new_arg(new ast_lid(param));
new_arg->env = env;
global_app = ast_ptr(new ast_app(std::move(global_app), std::move(new_arg)));
global_app->env = env;
}
translated_definitions.push_back({ def.first, std::move(global_app) });
}
in->translate(scope);
type_ptr ast_let::typecheck(type_mgr& mgr) {
definitions.typecheck(mgr);
return in->typecheck(mgr);
}
void ast_let::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(new instruction_alloc(translated_definitions.size())));
env_ptr new_env = env;
for(auto& def : translated_definitions) {
new_env = env_ptr(new env_var(def.first, std::move(new_env)));
}
int offset = translated_definitions.size() - 1;
for(auto& def : translated_definitions) {
def.second->compile(new_env, into);
into.push_back(instruction_ptr(new instruction_update(offset--)));
}
in->compile(new_env, into);
into.push_back(instruction_ptr(new instruction_slide(translated_definitions.size())));
throw 0;
}
void pattern_var::print(std::ostream& to) const {
to << var;
}
void pattern_var::find_variables(std::set<std::string>& into) const {
into.insert(var);
void pattern_var::insert_bindings(type_mgr& mgr, type_env_ptr& env) const {
env->bind(var, mgr.new_type());
}
void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const {
env->bind(var, t);
mgr.unify(env->lookup(var)->instantiate(mgr), t);
}
void pattern_constr::print(std::ostream& to) const {
@ -349,8 +271,10 @@ void pattern_constr::print(std::ostream& to) const {
}
}
void pattern_constr::find_variables(std::set<std::string>& into) const {
into.insert(params.begin(), params.end());
void pattern_constr::insert_bindings(type_mgr& mgr, type_env_ptr& env) const {
for(auto& param : params) {
env->bind(param, mgr.new_type());
}
}
void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const {
@ -363,7 +287,7 @@ void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) con
type_arr* arr = dynamic_cast<type_arr*>(constructor_type.get());
if(!arr) throw type_error("too many parameters in constructor pattern");
env->bind(param, arr->left);
mgr.unify(env->lookup(param)->instantiate(mgr), arr->left);
constructor_type = arr->right;
}

View File

@ -8,7 +8,6 @@
#include "instruction.hpp"
#include "env.hpp"
#include "definition.hpp"
#include "global_scope.hpp"
struct ast {
type_env_ptr env;
@ -16,9 +15,9 @@ struct ast {
virtual ~ast() = default;
virtual void print(int indent, std::ostream& to) const = 0;
virtual void find_free(std::set<std::string>& into) = 0;
virtual type_ptr typecheck(type_mgr& mgr, type_env_ptr& env) = 0;
virtual void translate(global_scope& scope) = 0;
virtual void find_free(type_mgr& mgr,
type_env_ptr& env, std::set<std::string>& into) = 0;
virtual type_ptr typecheck(type_mgr& mgr) = 0;
virtual void compile(const env_ptr& env,
std::vector<instruction_ptr>& into) const = 0;
};
@ -29,7 +28,7 @@ struct pattern {
virtual ~pattern() = default;
virtual void print(std::ostream& to) const = 0;
virtual void find_variables(std::set<std::string>& into) const = 0;
virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) const = 0;
virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const = 0;
};
@ -52,9 +51,8 @@ struct ast_int : public ast {
: value(v) {}
void print(int indent, std::ostream& to) const;
void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
};
@ -65,9 +63,8 @@ struct ast_lid : public ast {
: id(std::move(i)) {}
void print(int indent, std::ostream& to) const;
void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
};
@ -78,9 +75,8 @@ struct ast_uid : public ast {
: id(std::move(i)) {}
void print(int indent, std::ostream& to) const;
void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
};
@ -93,9 +89,8 @@ struct ast_binop : public ast {
: op(o), left(std::move(l)), right(std::move(r)) {}
void print(int indent, std::ostream& to) const;
void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
};
@ -107,9 +102,8 @@ struct ast_app : public ast {
: left(std::move(l)), right(std::move(r)) {}
void print(int indent, std::ostream& to) const;
void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
};
@ -122,27 +116,21 @@ struct ast_case : public ast {
: of(std::move(o)), branches(std::move(b)) {}
void print(int indent, std::ostream& to) const;
void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
};
struct ast_let : public ast {
using basic_definition = std::pair<std::string, ast_ptr>;
definition_group definitions;
ast_ptr in;
std::vector<basic_definition> translated_definitions;
ast_let(definition_group g, ast_ptr i)
: definitions(std::move(g)), in(std::move(i)) {}
void print(int indent, std::ostream& to) const;
void find_free(std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr, type_env_ptr& env);
void translate(global_scope& scope);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
};
@ -153,7 +141,7 @@ struct pattern_var : public pattern {
: var(std::move(v)) {}
void print(std::ostream &to) const;
void find_variables(std::set<std::string>& into) const;
void insert_bindings(type_mgr& mgr, type_env_ptr& env) const;
void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const;
};
@ -165,6 +153,6 @@ struct pattern_constr : public pattern {
: constr(std::move(c)), params(std::move(p)) {}
void print(std::ostream &to) const;
void find_variables(std::set<std::string>& into) const;
virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) const;
virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const;
};

View File

@ -10,15 +10,9 @@
#include <llvm/IR/Function.h>
#include <llvm/IR/Type.h>
void definition_defn::find_free() {
body->find_free(free_variables);
for(auto& param : params) {
free_variables.erase(param);
}
}
void definition_defn::insert_types(type_mgr& mgr, type_env_ptr& env, visibility v) {
void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) {
this->env = env;
var_env = type_scope(env);
return_type = mgr.new_type();
full_type = return_type;
@ -28,24 +22,39 @@ void definition_defn::insert_types(type_mgr& mgr, type_env_ptr& env, visibility
full_type = type_ptr(new type_arr(param_type, full_type));
var_env->bind(*it, param_type);
}
body->find_free(mgr, var_env, free_variables);
}
void definition_defn::insert_types(type_mgr& mgr, visibility v) {
env->bind(name, full_type, v);
}
void definition_defn::typecheck(type_mgr& mgr) {
type_ptr body_type = body->typecheck(mgr, var_env);
type_ptr body_type = body->typecheck(mgr);
mgr.unify(return_type, body_type);
}
global_function& definition_defn::into_global(global_scope& scope) {
std::vector<std::string> all_params;
for(auto& free : free_variables) {
if(env->is_global(free)) continue;
all_params.push_back(free);
void definition_defn::compile() {
env_ptr new_env = env_ptr(new env_offset(0, nullptr));
for(auto it = params.rbegin(); it != params.rend(); it++) {
new_env = env_ptr(new env_var(*it, new_env));
}
all_params.insert(all_params.end(), params.begin(), params.end());
body->translate(scope);
return scope.add_function(name, std::move(all_params), std::move(body));
body->compile(new_env, instructions);
instructions.push_back(instruction_ptr(new instruction_update(params.size())));
instructions.push_back(instruction_ptr(new instruction_pop(params.size())));
}
void definition_defn::declare_llvm(llvm_context& ctx) {
generated_function = ctx.create_custom_function(name, params.size());
}
void definition_defn::generate_llvm(llvm_context& ctx) {
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
for(auto& instruction : instructions) {
instruction->gen_llvm(ctx, generated_function);
}
ctx.builder.CreateRetVoid();
}
void definition_data::insert_types(type_env_ptr& env) {
@ -83,17 +92,28 @@ void definition_data::insert_constructors() const {
}
}
void definition_data::into_globals(global_scope& scope) {
void definition_data::generate_llvm(llvm_context& ctx) {
for(auto& constructor : constructors) {
global_constructor& c = scope.add_constructor(
constructor->name, constructor->tag, constructor->types.size());
env->set_mangled_name(constructor->name, c.name);
auto new_function =
ctx.create_custom_function(constructor->name, constructor->types.size());
std::vector<instruction_ptr> instructions;
instructions.push_back(instruction_ptr(
new instruction_pack(constructor->tag, constructor->types.size())
));
instructions.push_back(instruction_ptr(new instruction_update(0)));
ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
for (auto& instruction : instructions) {
instruction->gen_llvm(ctx, new_function);
}
ctx.builder.CreateRetVoid();
}
}
void definition_group::find_free(std::set<std::string>& into) {
void definition_group::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
this->env = type_scope(env);
for(auto& def_pair : defs_defn) {
def_pair.second->find_free();
def_pair.second->find_free(mgr, env);
for(auto& free_var : def_pair.second->free_variables) {
if(defs_defn.find(free_var) == defs_defn.end()) {
into.insert(free_var);
@ -104,11 +124,9 @@ void definition_group::find_free(std::set<std::string>& into) {
}
}
void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) {
this->env = type_scope(env);
void definition_group::typecheck(type_mgr& mgr) {
for(auto& def_data : defs_data) {
def_data.second->insert_types(this->env);
def_data.second->insert_types(env);
}
for(auto& def_data : defs_data) {
def_data.second->insert_constructors();
@ -117,7 +135,7 @@ void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) {
function_graph dependency_graph;
for(auto& def_defn : defs_defn) {
def_defn.second->find_free();
def_defn.second->find_free(mgr, env);
dependency_graph.add_function(def_defn.second->name);
for(auto& dependency : def_defn.second->nearby_variables) {
@ -132,14 +150,14 @@ void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) {
auto& group = *it;
for(auto& def_defnn_name : group->members) {
auto& def_defn = defs_defn.find(def_defnn_name)->second;
def_defn->insert_types(mgr, this->env, vis);
def_defn->insert_types(mgr, vis);
}
for(auto& def_defnn_name : group->members) {
auto& def_defn = defs_defn.find(def_defnn_name)->second;
def_defn->typecheck(mgr);
}
for(auto& def_defnn_name : group->members) {
this->env->generalize(def_defnn_name, mgr);
env->generalize(def_defnn_name, mgr);
}
}
}

View File

@ -7,7 +7,6 @@
#include "llvm_context.hpp"
#include "parsed_type.hpp"
#include "type_env.hpp"
#include "global_scope.hpp"
struct ast;
using ast_ptr = std::unique_ptr<ast>;
@ -35,16 +34,21 @@ struct definition_defn {
type_ptr full_type;
type_ptr return_type;
std::vector<instruction_ptr> instructions;
llvm::Function* generated_function;
definition_defn(std::string n, std::vector<std::string> p, ast_ptr b)
: name(std::move(n)), params(std::move(p)), body(std::move(b)) {
}
void find_free();
void insert_types(type_mgr& mgr, type_env_ptr& env, visibility v);
void find_free(type_mgr& mgr, type_env_ptr& env);
void insert_types(type_mgr& mgr, visibility v);
void typecheck(type_mgr& mgr);
global_function& into_global(global_scope& scope);
void compile();
void declare_llvm(llvm_context& ctx);
void generate_llvm(llvm_context& ctx);
};
using definition_defn_ptr = std::unique_ptr<definition_defn>;
@ -64,8 +68,7 @@ struct definition_data {
void insert_types(type_env_ptr& env);
void insert_constructors() const;
void into_globals(global_scope& scope);
void generate_llvm(llvm_context& ctx);
};
using definition_data_ptr = std::unique_ptr<definition_data>;
@ -78,6 +81,6 @@ struct definition_group {
definition_group(visibility v = visibility::local) : vis(v) {}
void find_free(std::set<std::string>& into);
void typecheck(type_mgr& mgr, type_env_ptr& env);
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
void typecheck(type_mgr& mgr);
};

View File

@ -15,7 +15,7 @@ struct env_var : public env {
std::string name;
env_ptr parent;
env_var(std::string n, env_ptr p)
env_var(std::string& n, env_ptr p)
: name(std::move(n)), parent(std::move(p)) {}
int get_offset(const std::string& name) const;

View File

@ -1,83 +0,0 @@
#include "global_scope.hpp"
#include "ast.hpp"
void global_function::compile() {
env_ptr new_env = env_ptr(new env_offset(0, nullptr));
for(auto it = params.rbegin(); it != params.rend(); it++) {
new_env = env_ptr(new env_var(*it, new_env));
}
body->compile(new_env, instructions);
instructions.push_back(instruction_ptr(new instruction_update(params.size())));
instructions.push_back(instruction_ptr(new instruction_pop(params.size())));
}
void global_function::declare_llvm(llvm_context& ctx) {
generated_function = ctx.create_custom_function(name, params.size());
}
void global_function::generate_llvm(llvm_context& ctx) {
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
for(auto& instruction : instructions) {
instruction->gen_llvm(ctx, generated_function);
}
ctx.builder.CreateRetVoid();
}
void global_constructor::generate_llvm(llvm_context& ctx) {
auto new_function =
ctx.create_custom_function(name, arity);
std::vector<instruction_ptr> instructions;
instructions.push_back(instruction_ptr(new instruction_pack(tag, arity)));
instructions.push_back(instruction_ptr(new instruction_update(0)));
ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
for (auto& instruction : instructions) {
instruction->gen_llvm(ctx, new_function);
}
ctx.builder.CreateRetVoid();
}
global_function& global_scope::add_function(std::string n, std::vector<std::string> ps, ast_ptr b) {
global_function* new_function = new global_function(mangle_name(n), std::move(ps), std::move(b));
functions.push_back(global_function_ptr(new_function));
return *new_function;
}
global_constructor& global_scope::add_constructor(std::string n, int8_t t, size_t a) {
global_constructor* new_constructor = new global_constructor(mangle_name(n), t, a);
constructors.push_back(global_constructor_ptr(new_constructor));
return *new_constructor;
}
void global_scope::compile() {
for(auto& function : functions) {
function->compile();
}
}
void global_scope::generate_llvm(llvm_context& ctx) {
for(auto& constructor : constructors) {
constructor->generate_llvm(ctx);
}
for(auto& function : functions) {
function->declare_llvm(ctx);
}
for(auto& function : functions) {
function->generate_llvm(ctx);
}
}
std::string global_scope::mangle_name(const std::string& n) {
auto occurence_it = occurence_count.find(n);
int occurence = 0;
if(occurence_it != occurence_count.end()) {
occurence = occurence_it->second + 1;
}
occurence_count[n] = occurence;
std::string final_name = n;
if (occurence != 0) {
final_name += "_";
final_name += std::to_string(occurence);
}
return final_name;
}

View File

@ -1,59 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <llvm/IR/Function.h>
#include "instruction.hpp"
struct ast;
using ast_ptr = std::unique_ptr<ast>;
struct global_definition {
virtual void generate_llvm(llvm_context& ctx) = 0;
};
struct global_function : global_definition {
std::string name;
std::vector<std::string> params;
ast_ptr body;
std::vector<instruction_ptr> instructions;
llvm::Function* generated_function;
global_function(std::string n, std::vector<std::string> ps, ast_ptr b)
: name(std::move(n)), params(std::move(ps)), body(std::move(b)) {}
void compile();
void declare_llvm(llvm_context& ctx);
void generate_llvm(llvm_context& ctx);
};
using global_function_ptr = std::unique_ptr<global_function>;
struct global_constructor : global_definition {
std::string name;
int8_t tag;
size_t arity;
global_constructor(std::string n, int8_t t, size_t a)
: name(std::move(n)), tag(t), arity(a) {}
void generate_llvm(llvm_context& ctx);
};
using global_constructor_ptr = std::unique_ptr<global_constructor>;
struct global_scope {
std::map<std::string, int> occurence_count;
std::vector<global_function_ptr> functions;
std::vector<global_constructor_ptr> constructors;
global_function& add_function(std::string n, std::vector<std::string> ps, ast_ptr b);
global_constructor& add_constructor(std::string n, int8_t t, size_t a);
void compile();
void generate_llvm(llvm_context& ctx);
private:
std::string mangle_name(const std::string& n);
};

View File

@ -39,8 +39,8 @@ void typecheck_program(
env->bind("/", binop_type, visibility::global);
std::set<std::string> free;
defs.find_free(free);
defs.typecheck(mgr, env);
defs.find_free(mgr, env, free);
defs.typecheck(mgr);
for(auto& pair : defs.env->names) {
std::cout << pair.first << ": ";
@ -49,16 +49,15 @@ void typecheck_program(
}
}
global_scope translate_program(definition_group& group) {
global_scope scope;
for(auto& data : group.defs_data) {
data.second->into_globals(scope);
void compile_program(const std::map<std::string, definition_defn_ptr>& defs_defn) {
for(auto& def_defn : defs_defn) {
def_defn.second->compile();
for(auto& instruction : def_defn.second->instructions) {
instruction->print(0, std::cout);
}
for(auto& defn : group.defs_defn) {
auto& function = defn.second->into_global(scope);
function.body->env->parent->set_mangled_name(defn.first, function.name);
std::cout << std::endl;
}
return scope;
}
void gen_llvm_internal_op(llvm_context& ctx, binop op) {
@ -118,14 +117,24 @@ void output_llvm(llvm_context& ctx, const std::string& filename) {
}
}
void gen_llvm(global_scope& scope) {
void gen_llvm(
const std::map<std::string, definition_data_ptr>& defs_data,
const std::map<std::string, definition_defn_ptr>& defs_defn) {
llvm_context ctx;
gen_llvm_internal_op(ctx, PLUS);
gen_llvm_internal_op(ctx, MINUS);
gen_llvm_internal_op(ctx, TIMES);
gen_llvm_internal_op(ctx, DIVIDE);
scope.generate_llvm(ctx);
for(auto& def_data : defs_data) {
def_data.second->generate_llvm(ctx);
}
for(auto& def_defn : defs_defn) {
def_defn.second->declare_llvm(ctx);
}
for(auto& def_defn : defs_defn) {
def_defn.second->generate_llvm(ctx);
}
ctx.module.print(llvm::outs(), nullptr);
output_llvm(ctx, "program.o");
@ -146,9 +155,8 @@ int main() {
}
try {
typecheck_program(global_defs, mgr, env);
global_scope scope = translate_program(global_defs);
scope.compile();
gen_llvm(scope);
compile_program(global_defs.defs_defn);
gen_llvm(global_defs.defs_data, global_defs.defs_defn);
} catch(unification_error& err) {
std::cout << "failed to unify types: " << std::endl;
std::cout << " (1) \033[34m";

View File

@ -7,7 +7,7 @@
#include "parser.hpp"
#include "parsed_type.hpp"
definition_group global_defs;
definition_group global_defs(visibility::global);
extern yy::parser::symbol_type yylex();
@ -56,7 +56,7 @@ extern yy::parser::symbol_type yylex();
%%
program
: definitions { global_defs = std::move($1); global_defs.vis = visibility::global; }
: definitions { global_defs = std::move($1); }
;
definitions

View File

@ -24,26 +24,6 @@ type_scheme_ptr type_env::lookup(const std::string& name) const {
return nullptr;
}
bool type_env::is_global(const std::string& name) const {
auto it = names.find(name);
if(it != names.end()) return it->second.vis == visibility::global;
if(parent) return parent->is_global(name);
return false;
}
void type_env::set_mangled_name(const std::string& name, const std::string& mangled) {
auto it = names.find(name);
if(it != names.end()) it->second.mangled_name = mangled;
}
const std::string& type_env::get_mangled_name(const std::string& name) const {
auto it = names.find(name);
if(it != names.end())
return (it->second.mangled_name != "") ? it->second.mangled_name : name;
if(parent) return parent->get_mangled_name(name);
return name;
}
type_ptr type_env::lookup_type(const std::string& name) const {
auto it = type_names.find(name);
if(it != type_names.end()) return it->second;
@ -53,11 +33,11 @@ type_ptr type_env::lookup_type(const std::string& name) const {
void type_env::bind(const std::string& name, type_ptr t, visibility v) {
type_scheme_ptr new_scheme(new type_scheme(std::move(t)));
names[name] = variable_data(std::move(new_scheme), v, "");
names[name] = variable_data(std::move(new_scheme), v);
}
void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) {
names[name] = variable_data(std::move(t), v, "");
names[name] = variable_data(std::move(t), v);
}
void type_env::bind_type(const std::string& type_name, type_ptr t) {

View File

@ -13,12 +13,11 @@ struct type_env {
struct variable_data {
type_scheme_ptr type;
visibility vis;
std::string mangled_name;
variable_data()
: variable_data(nullptr, visibility::local, "") {}
variable_data(type_scheme_ptr t, visibility v, std::string n)
: type(std::move(t)), vis(v), mangled_name(std::move(n)) {}
: variable_data(nullptr, visibility::local) {}
variable_data(type_scheme_ptr t, visibility v)
: type(std::move(t)), vis(v) {}
};
type_env_ptr parent;
@ -32,9 +31,6 @@ struct type_env {
void find_free_except(const type_mgr& mgr, const std::string& avoid,
std::set<std::string>& into) const;
type_scheme_ptr lookup(const std::string& name) const;
bool is_global(const std::string& name) const;
void set_mangled_name(const std::string& name, const std::string& mangled);
const std::string& get_mangled_name(const std::string& name) const;
type_ptr lookup_type(const std::string& name) const;
void bind(const std::string& name, type_ptr t,
visibility v = visibility::local);