Start working on translation.
This commit is contained in:
parent
08c8aca144
commit
e7229e644f
|
@ -3,6 +3,7 @@
|
|||
#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 << " ";
|
||||
|
@ -21,6 +22,10 @@ type_ptr ast_int::typecheck(type_mgr& mgr) {
|
|||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
void ast_lid::translate(global_scope& scope) {
|
||||
|
||||
}
|
||||
|
||||
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
|
||||
into.push_back(instruction_ptr(
|
||||
env->has_variable(id) ?
|
||||
|
@ -59,6 +68,10 @@ 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(id)));
|
||||
}
|
||||
|
@ -90,6 +103,11 @@ type_ptr ast_binop::typecheck(type_mgr& mgr) {
|
|||
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);
|
||||
|
@ -122,6 +140,11 @@ type_ptr ast_app::typecheck(type_mgr& mgr) {
|
|||
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);
|
||||
|
@ -170,6 +193,13 @@ type_ptr ast_case::typecheck(type_mgr& mgr) {
|
|||
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());
|
||||
|
@ -248,8 +278,36 @@ type_ptr ast_let::typecheck(type_mgr& 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 {
|
||||
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 {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "instruction.hpp"
|
||||
#include "env.hpp"
|
||||
#include "definition.hpp"
|
||||
#include "global_scope.hpp"
|
||||
|
||||
struct ast {
|
||||
type_env_ptr env;
|
||||
|
@ -18,6 +19,7 @@ struct ast {
|
|||
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 translate(global_scope& scope) = 0;
|
||||
virtual void compile(const env_ptr& env,
|
||||
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 find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||
type_ptr typecheck(type_mgr& mgr);
|
||||
void translate(global_scope& scope);
|
||||
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 find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||
type_ptr typecheck(type_mgr& mgr);
|
||||
void translate(global_scope& scope);
|
||||
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 find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||
type_ptr typecheck(type_mgr& mgr);
|
||||
void translate(global_scope& scope);
|
||||
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 find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||
type_ptr typecheck(type_mgr& mgr);
|
||||
void translate(global_scope& scope);
|
||||
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 find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||
type_ptr typecheck(type_mgr& mgr);
|
||||
void translate(global_scope& scope);
|
||||
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 find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||
type_ptr typecheck(type_mgr& mgr);
|
||||
void translate(global_scope& scope);
|
||||
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(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into);
|
||||
type_ptr typecheck(type_mgr& mgr);
|
||||
void translate(global_scope& scope);
|
||||
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -35,26 +35,16 @@ void definition_defn::typecheck(type_mgr& mgr) {
|
|||
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) {
|
||||
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);
|
||||
global_definition_ptr& 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);
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#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>;
|
||||
|
@ -34,10 +35,6 @@ 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)) {
|
||||
|
||||
|
@ -46,9 +43,8 @@ struct definition_defn {
|
|||
void find_free(type_mgr& mgr, type_env_ptr& env);
|
||||
void insert_types(type_mgr& mgr, visibility v);
|
||||
void typecheck(type_mgr& mgr);
|
||||
void compile();
|
||||
void declare_llvm(llvm_context& ctx);
|
||||
void generate_llvm(llvm_context& ctx);
|
||||
|
||||
global_definition_ptr& into_global(global_scope& scope);
|
||||
};
|
||||
|
||||
using definition_defn_ptr = std::unique_ptr<definition_defn>;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,6 +24,13 @@ 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -31,6 +31,7 @@ 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;
|
||||
type_ptr lookup_type(const std::string& name) const;
|
||||
void bind(const std::string& name, type_ptr t,
|
||||
visibility v = visibility::local);
|
||||
|
|
Loading…
Reference in New Issue
Block a user