Start working on translation.

This commit is contained in:
Danila Fedorin 2020-05-31 18:52:52 -07:00
parent 08c8aca144
commit e7229e644f
7 changed files with 92 additions and 27 deletions

View File

@ -3,6 +3,7 @@
#include "binop.hpp" #include "binop.hpp"
#include "error.hpp" #include "error.hpp"
#include "type_env.hpp" #include "type_env.hpp"
#include "env.hpp"
static void print_indent(int n, std::ostream& to) { static void print_indent(int n, std::ostream& to) {
while(n--) to << " "; while(n--) to << " ";
@ -21,6 +22,10 @@ type_ptr ast_int::typecheck(type_mgr& mgr) {
return type_ptr(new type_app(env->lookup_type("Int"))); return type_ptr(new type_app(env->lookup_type("Int")));
} }
void ast_int::translate(global_scope& scope) {
}
void ast_int::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const { void ast_int::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(new instruction_pushint(value))); into.push_back(instruction_ptr(new instruction_pushint(value)));
} }
@ -39,6 +44,10 @@ type_ptr ast_lid::typecheck(type_mgr& mgr) {
return env->lookup(id)->instantiate(mgr); return env->lookup(id)->instantiate(mgr);
} }
void ast_lid::translate(global_scope& scope) {
}
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const { void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr( into.push_back(instruction_ptr(
env->has_variable(id) ? env->has_variable(id) ?
@ -59,6 +68,10 @@ type_ptr ast_uid::typecheck(type_mgr& mgr) {
return env->lookup(id)->instantiate(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 { void ast_uid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(new instruction_pushglobal(id))); into.push_back(instruction_ptr(new instruction_pushglobal(id)));
} }
@ -90,6 +103,11 @@ type_ptr ast_binop::typecheck(type_mgr& mgr) {
return return_type; 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 { void ast_binop::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
right->compile(env, into); right->compile(env, into);
left->compile(env_ptr(new env_offset(1, env)), into); left->compile(env_ptr(new env_offset(1, env)), into);
@ -122,6 +140,11 @@ type_ptr ast_app::typecheck(type_mgr& mgr) {
return return_type; 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 { void ast_app::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
right->compile(env, into); right->compile(env, into);
left->compile(env_ptr(new env_offset(1, env)), into); left->compile(env_ptr(new env_offset(1, env)), into);
@ -170,6 +193,13 @@ type_ptr ast_case::typecheck(type_mgr& mgr) {
return branch_type; 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 { 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_app* app_type = dynamic_cast<type_app*>(input_type.get());
type_data* type = dynamic_cast<type_data*>(app_type->constructor.get()); type_data* type = dynamic_cast<type_data*>(app_type->constructor.get());
@ -248,8 +278,36 @@ type_ptr ast_let::typecheck(type_mgr& mgr) {
return in->typecheck(mgr); return in->typecheck(mgr);
} }
void ast_let::translate(global_scope& 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;
ast_ptr global_app(new ast_lid(global_definition->name));
for(auto& param : global_definition->params) {
if(!(captured--)) break;
ast_ptr new_arg(new ast_lid(param));
global_app = ast_ptr(new ast_app(std::move(global_app), std::move(new_arg)));
}
translated_definitions.push_back({ global_definition->name, std::move(global_app) });
}
in->translate(scope);
}
void ast_let::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const { void ast_let::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
throw 0; 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);
} }
void pattern_var::print(std::ostream& to) const { void pattern_var::print(std::ostream& to) const {

View File

@ -8,6 +8,7 @@
#include "instruction.hpp" #include "instruction.hpp"
#include "env.hpp" #include "env.hpp"
#include "definition.hpp" #include "definition.hpp"
#include "global_scope.hpp"
struct ast { struct ast {
type_env_ptr env; type_env_ptr env;
@ -18,6 +19,7 @@ struct ast {
virtual void find_free(type_mgr& mgr, virtual void find_free(type_mgr& mgr,
type_env_ptr& env, std::set<std::string>& into) = 0; type_env_ptr& env, std::set<std::string>& into) = 0;
virtual type_ptr typecheck(type_mgr& mgr) = 0; virtual type_ptr typecheck(type_mgr& mgr) = 0;
virtual void translate(global_scope& scope) = 0;
virtual void compile(const env_ptr& env, virtual void compile(const env_ptr& env,
std::vector<instruction_ptr>& into) const = 0; std::vector<instruction_ptr>& into) const = 0;
}; };
@ -53,6 +55,7 @@ struct ast_int : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr);
void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -65,6 +68,7 @@ struct ast_lid : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr);
void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -77,6 +81,7 @@ struct ast_uid : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr);
void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -91,6 +96,7 @@ struct ast_binop : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr);
void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -104,6 +110,7 @@ struct ast_app : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr);
void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
@ -118,19 +125,25 @@ struct ast_case : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr);
void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
struct ast_let : public ast { struct ast_let : public ast {
using basic_definition = std::pair<std::string, ast_ptr>;
definition_group definitions; definition_group definitions;
ast_ptr in; ast_ptr in;
std::vector<basic_definition> translated_definitions;
ast_let(definition_group g, ast_ptr i) ast_let(definition_group g, ast_ptr i)
: definitions(std::move(g)), in(std::move(i)) {} : definitions(std::move(g)), in(std::move(i)) {}
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into); void find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
type_ptr typecheck(type_mgr& mgr); type_ptr typecheck(type_mgr& mgr);
void translate(global_scope& scope);
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const; void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };

View File

@ -35,26 +35,16 @@ void definition_defn::typecheck(type_mgr& mgr) {
mgr.unify(return_type, body_type); mgr.unify(return_type, body_type);
} }
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));
}
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) { global_definition_ptr& definition_defn::into_global(global_scope& scope) {
generated_function = ctx.create_custom_function(name, params.size()); std::vector<std::string> all_params;
} for(auto& free : free_variables) {
if(env->is_global(free)) continue;
void definition_defn::generate_llvm(llvm_context& ctx) { all_params.push_back(free);
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
for(auto& instruction : instructions) {
instruction->gen_llvm(ctx, generated_function);
} }
ctx.builder.CreateRetVoid(); all_params.insert(all_params.end(), params.begin(), params.end());
translate(body, scope);
return scope.add_definition(name, std::move(all_params), std::move(body));
} }
void definition_data::insert_types(type_env_ptr& env) { void definition_data::insert_types(type_env_ptr& env) {

View File

@ -7,6 +7,7 @@
#include "llvm_context.hpp" #include "llvm_context.hpp"
#include "parsed_type.hpp" #include "parsed_type.hpp"
#include "type_env.hpp" #include "type_env.hpp"
#include "global_scope.hpp"
struct ast; struct ast;
using ast_ptr = std::unique_ptr<ast>; using ast_ptr = std::unique_ptr<ast>;
@ -34,10 +35,6 @@ struct definition_defn {
type_ptr full_type; type_ptr full_type;
type_ptr return_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) 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)) { : name(std::move(n)), params(std::move(p)), body(std::move(b)) {
@ -46,9 +43,8 @@ struct definition_defn {
void find_free(type_mgr& mgr, type_env_ptr& env); void find_free(type_mgr& mgr, type_env_ptr& env);
void insert_types(type_mgr& mgr, visibility v); void insert_types(type_mgr& mgr, visibility v);
void typecheck(type_mgr& mgr); void typecheck(type_mgr& mgr);
void compile();
void declare_llvm(llvm_context& ctx); global_definition_ptr& into_global(global_scope& scope);
void generate_llvm(llvm_context& ctx);
}; };
using definition_defn_ptr = std::unique_ptr<definition_defn>; using definition_defn_ptr = std::unique_ptr<definition_defn>;

View File

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

View File

@ -24,6 +24,13 @@ type_scheme_ptr type_env::lookup(const std::string& name) const {
return nullptr; 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;
}
type_ptr type_env::lookup_type(const std::string& name) const { type_ptr type_env::lookup_type(const std::string& name) const {
auto it = type_names.find(name); auto it = type_names.find(name);
if(it != type_names.end()) return it->second; if(it != type_names.end()) return it->second;

View File

@ -31,6 +31,7 @@ struct type_env {
void find_free_except(const type_mgr& mgr, const std::string& avoid, void find_free_except(const type_mgr& mgr, const std::string& avoid,
std::set<std::string>& into) const; std::set<std::string>& into) const;
type_scheme_ptr lookup(const std::string& name) const; type_scheme_ptr lookup(const std::string& name) const;
bool is_global(const std::string& name) const;
type_ptr lookup_type(const std::string& name) const; type_ptr lookup_type(const std::string& name) const;
void bind(const std::string& name, type_ptr t, void bind(const std::string& name, type_ptr t,
visibility v = visibility::local); visibility v = visibility::local);