Start working on translation.
This commit is contained in:
parent
6d1be9527e
commit
baf7427737
60
12/ast.cpp
60
12/ast.cpp
|
@ -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 {
|
||||||
|
|
13
12/ast.hpp
13
12/ast.hpp
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
all_params.push_back(free);
|
||||||
}
|
}
|
||||||
|
all_params.insert(all_params.end(), params.begin(), params.end());
|
||||||
void definition_defn::generate_llvm(llvm_context& ctx) {
|
translate(body, scope);
|
||||||
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
|
return scope.add_definition(name, std::move(all_params), std::move(body));
|
||||||
for(auto& instruction : instructions) {
|
|
||||||
instruction->gen_llvm(ctx, generated_function);
|
|
||||||
}
|
|
||||||
ctx.builder.CreateRetVoid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_data::insert_types(type_env_ptr& env) {
|
void definition_data::insert_types(type_env_ptr& env) {
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user