Separate definitions in compiler series
This commit is contained in:
parent
2e74291ac9
commit
c286c9edcc
91
10/ast.cpp
91
10/ast.cpp
|
@ -2,6 +2,7 @@
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include "binop.hpp"
|
#include "binop.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "type_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 << " ";
|
||||||
|
@ -12,7 +13,11 @@ void ast_int::print(int indent, std::ostream& to) const {
|
||||||
to << "INT: " << value << std::endl;
|
to << "INT: " << value << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) {
|
void ast_int::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
|
||||||
|
this->env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_ptr ast_int::typecheck(type_mgr& mgr) {
|
||||||
return type_ptr(new type_base("Int"));
|
return type_ptr(new type_base("Int"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +30,13 @@ void ast_lid::print(int indent, std::ostream& to) const {
|
||||||
to << "LID: " << id << std::endl;
|
to << "LID: " << id << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) {
|
void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
|
||||||
return env.lookup(id);
|
this->env = env;
|
||||||
|
if(env->lookup(id) == nullptr) into.insert(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_ptr ast_lid::typecheck(type_mgr& mgr) {
|
||||||
|
return env->lookup(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -41,8 +51,12 @@ void ast_uid::print(int indent, std::ostream& to) const {
|
||||||
to << "UID: " << id << std::endl;
|
to << "UID: " << id << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) {
|
void ast_uid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
|
||||||
return env.lookup(id);
|
this->env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_ptr ast_uid::typecheck(type_mgr& mgr) {
|
||||||
|
return env->lookup(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -56,10 +70,16 @@ void ast_binop::print(int indent, std::ostream& to) const {
|
||||||
right->print(indent + 1, to);
|
right->print(indent + 1, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) {
|
void ast_binop::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
|
||||||
type_ptr ltype = left->typecheck(mgr, env);
|
this->env = env;
|
||||||
type_ptr rtype = right->typecheck(mgr, env);
|
left->find_free(mgr, env, into);
|
||||||
type_ptr ftype = env.lookup(op_name(op));
|
right->find_free(mgr, env, into);
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op));
|
if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op));
|
||||||
|
|
||||||
type_ptr return_type = mgr.new_type();
|
type_ptr return_type = mgr.new_type();
|
||||||
|
@ -86,9 +106,15 @@ void ast_app::print(int indent, std::ostream& to) const {
|
||||||
right->print(indent + 1, to);
|
right->print(indent + 1, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) {
|
void ast_app::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
|
||||||
type_ptr ltype = left->typecheck(mgr, env);
|
this->env = env;
|
||||||
type_ptr rtype = right->typecheck(mgr, env);
|
left->find_free(mgr, env, into);
|
||||||
|
right->find_free(mgr, env, into);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 return_type = mgr.new_type();
|
||||||
type_ptr arrow = type_ptr(new type_arr(rtype, return_type));
|
type_ptr arrow = type_ptr(new type_arr(rtype, return_type));
|
||||||
|
@ -113,15 +139,24 @@ void ast_case::print(int indent, std::ostream& to) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) {
|
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) {
|
||||||
|
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_var* var;
|
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();
|
type_ptr branch_type = mgr.new_type();
|
||||||
|
|
||||||
for(auto& branch : branches) {
|
for(auto& branch : branches) {
|
||||||
type_env new_env = env.scope();
|
branch->pat->typecheck(case_type, mgr, branch->expr->env);
|
||||||
branch->pat->match(case_type, mgr, new_env);
|
type_ptr curr_branch_type = branch->expr->typecheck(mgr);
|
||||||
type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env);
|
|
||||||
mgr.unify(branch_type, curr_branch_type);
|
mgr.unify(branch_type, curr_branch_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,8 +227,12 @@ void pattern_var::print(std::ostream& to) const {
|
||||||
to << var;
|
to << var;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const {
|
void pattern_var::insert_bindings(type_mgr& mgr, type_env_ptr& env) const {
|
||||||
env.bind(var, t);
|
env->bind(var, mgr.new_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const {
|
||||||
|
mgr.unify(env->lookup(var), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pattern_constr::print(std::ostream& to) const {
|
void pattern_constr::print(std::ostream& to) const {
|
||||||
|
@ -203,17 +242,23 @@ void pattern_constr::print(std::ostream& to) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const {
|
void pattern_constr::insert_bindings(type_mgr& mgr, type_env_ptr& env) const {
|
||||||
type_ptr constructor_type = env.lookup(constr);
|
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 {
|
||||||
|
type_ptr constructor_type = env->lookup(constr);
|
||||||
if(!constructor_type) {
|
if(!constructor_type) {
|
||||||
throw type_error(std::string("pattern using unknown constructor ") + constr);
|
throw type_error(std::string("pattern using unknown constructor ") + constr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < params.size(); i++) {
|
for(auto& param : params) {
|
||||||
type_arr* arr = dynamic_cast<type_arr*>(constructor_type.get());
|
type_arr* arr = dynamic_cast<type_arr*>(constructor_type.get());
|
||||||
if(!arr) throw type_error("too many parameters in constructor pattern");
|
if(!arr) throw type_error("too many parameters in constructor pattern");
|
||||||
|
|
||||||
env.bind(params[i], arr->left);
|
mgr.unify(env->lookup(param), arr->left);
|
||||||
constructor_type = arr->right;
|
constructor_type = arr->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
10/ast.hpp
34
10/ast.hpp
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
#include "type.hpp"
|
#include "type.hpp"
|
||||||
#include "type_env.hpp"
|
#include "type_env.hpp"
|
||||||
#include "binop.hpp"
|
#include "binop.hpp"
|
||||||
|
@ -8,10 +9,14 @@
|
||||||
#include "env.hpp"
|
#include "env.hpp"
|
||||||
|
|
||||||
struct ast {
|
struct ast {
|
||||||
|
type_env_ptr env;
|
||||||
|
|
||||||
virtual ~ast() = default;
|
virtual ~ast() = default;
|
||||||
|
|
||||||
virtual void print(int indent, std::ostream& to) const = 0;
|
virtual void print(int indent, std::ostream& to) const = 0;
|
||||||
virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) = 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,
|
virtual void compile(const env_ptr& env,
|
||||||
std::vector<instruction_ptr>& into) const = 0;
|
std::vector<instruction_ptr>& into) const = 0;
|
||||||
};
|
};
|
||||||
|
@ -22,7 +27,8 @@ struct pattern {
|
||||||
virtual ~pattern() = default;
|
virtual ~pattern() = default;
|
||||||
|
|
||||||
virtual void print(std::ostream& to) const = 0;
|
virtual void print(std::ostream& to) const = 0;
|
||||||
virtual void match(type_ptr t, type_mgr& mgr, type_env& env) 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
using pattern_ptr = std::unique_ptr<pattern>;
|
using pattern_ptr = std::unique_ptr<pattern>;
|
||||||
|
@ -44,7 +50,8 @@ struct ast_int : public ast {
|
||||||
: value(v) {}
|
: value(v) {}
|
||||||
|
|
||||||
void print(int indent, std::ostream& to) const;
|
void print(int indent, std::ostream& to) const;
|
||||||
type_ptr typecheck(type_mgr& mgr, const type_env& env);
|
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;
|
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,7 +62,8 @@ struct ast_lid : public ast {
|
||||||
: id(std::move(i)) {}
|
: id(std::move(i)) {}
|
||||||
|
|
||||||
void print(int indent, std::ostream& to) const;
|
void print(int indent, std::ostream& to) const;
|
||||||
type_ptr typecheck(type_mgr& mgr, const type_env& env);
|
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;
|
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,7 +74,8 @@ struct ast_uid : public ast {
|
||||||
: id(std::move(i)) {}
|
: id(std::move(i)) {}
|
||||||
|
|
||||||
void print(int indent, std::ostream& to) const;
|
void print(int indent, std::ostream& to) const;
|
||||||
type_ptr typecheck(type_mgr& mgr, const type_env& env);
|
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;
|
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,7 +88,8 @@ struct ast_binop : public ast {
|
||||||
: op(o), left(std::move(l)), right(std::move(r)) {}
|
: op(o), left(std::move(l)), right(std::move(r)) {}
|
||||||
|
|
||||||
void print(int indent, std::ostream& to) const;
|
void print(int indent, std::ostream& to) const;
|
||||||
type_ptr typecheck(type_mgr& mgr, const type_env& env);
|
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;
|
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,7 +101,8 @@ struct ast_app : public ast {
|
||||||
: left(std::move(l)), right(std::move(r)) {}
|
: left(std::move(l)), right(std::move(r)) {}
|
||||||
|
|
||||||
void print(int indent, std::ostream& to) const;
|
void print(int indent, std::ostream& to) const;
|
||||||
type_ptr typecheck(type_mgr& mgr, const type_env& env);
|
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;
|
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,7 +115,8 @@ struct ast_case : public ast {
|
||||||
: of(std::move(o)), branches(std::move(b)) {}
|
: of(std::move(o)), branches(std::move(b)) {}
|
||||||
|
|
||||||
void print(int indent, std::ostream& to) const;
|
void print(int indent, std::ostream& to) const;
|
||||||
type_ptr typecheck(type_mgr& mgr, const type_env& env);
|
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;
|
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -115,7 +127,8 @@ struct pattern_var : public pattern {
|
||||||
: var(std::move(v)) {}
|
: var(std::move(v)) {}
|
||||||
|
|
||||||
void print(std::ostream &to) const;
|
void print(std::ostream &to) const;
|
||||||
void match(type_ptr t, type_mgr& mgr, type_env& env) 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pattern_constr : public pattern {
|
struct pattern_constr : public pattern {
|
||||||
|
@ -126,5 +139,6 @@ struct pattern_constr : public pattern {
|
||||||
: constr(std::move(c)), params(std::move(p)) {}
|
: constr(std::move(c)), params(std::move(p)) {}
|
||||||
|
|
||||||
void print(std::ostream &to) const;
|
void print(std::ostream &to) const;
|
||||||
void match(type_ptr t, type_mgr&, type_env& env) 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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,35 +3,33 @@
|
||||||
#include "ast.hpp"
|
#include "ast.hpp"
|
||||||
#include "instruction.hpp"
|
#include "instruction.hpp"
|
||||||
#include "llvm_context.hpp"
|
#include "llvm_context.hpp"
|
||||||
|
#include "type_env.hpp"
|
||||||
#include <llvm/IR/DerivedTypes.h>
|
#include <llvm/IR/DerivedTypes.h>
|
||||||
#include <llvm/IR/Function.h>
|
#include <llvm/IR/Function.h>
|
||||||
#include <llvm/IR/Type.h>
|
#include <llvm/IR/Type.h>
|
||||||
|
|
||||||
void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) {
|
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();
|
return_type = mgr.new_type();
|
||||||
type_ptr full_type = return_type;
|
full_type = return_type;
|
||||||
|
|
||||||
for(auto it = params.rbegin(); it != params.rend(); it++) {
|
for(auto it = params.rbegin(); it != params.rend(); it++) {
|
||||||
type_ptr param_type = mgr.new_type();
|
type_ptr param_type = mgr.new_type();
|
||||||
full_type = type_ptr(new type_arr(param_type, full_type));
|
full_type = type_ptr(new type_arr(param_type, full_type));
|
||||||
param_types.push_back(param_type);
|
var_env->bind(*it, param_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
env.bind(name, full_type);
|
body->find_free(mgr, var_env, free_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const {
|
void definition_defn::insert_types(type_mgr& mgr) {
|
||||||
type_env new_env = env.scope();
|
env->bind(name, full_type);
|
||||||
auto param_it = params.begin();
|
|
||||||
auto type_it = param_types.rbegin();
|
|
||||||
|
|
||||||
while(param_it != params.end() && type_it != param_types.rend()) {
|
|
||||||
new_env.bind(*param_it, *type_it);
|
|
||||||
param_it++;
|
|
||||||
type_it++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type_ptr body_type = body->typecheck(mgr, new_env);
|
void definition_defn::typecheck(type_mgr& mgr) {
|
||||||
|
type_ptr body_type = body->typecheck(mgr);
|
||||||
mgr.unify(return_type, body_type);
|
mgr.unify(return_type, body_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,11 +42,12 @@ void definition_defn::compile() {
|
||||||
instructions.push_back(instruction_ptr(new instruction_update(params.size())));
|
instructions.push_back(instruction_ptr(new instruction_update(params.size())));
|
||||||
instructions.push_back(instruction_ptr(new instruction_pop(params.size())));
|
instructions.push_back(instruction_ptr(new instruction_pop(params.size())));
|
||||||
}
|
}
|
||||||
void definition_defn::gen_llvm_first(llvm_context& ctx) {
|
|
||||||
|
void definition_defn::declare_llvm(llvm_context& ctx) {
|
||||||
generated_function = ctx.create_custom_function(name, params.size());
|
generated_function = ctx.create_custom_function(name, params.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_defn::gen_llvm_second(llvm_context& ctx) {
|
void definition_defn::generate_llvm(llvm_context& ctx) {
|
||||||
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
|
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
|
||||||
for(auto& instruction : instructions) {
|
for(auto& instruction : instructions) {
|
||||||
instruction->gen_llvm(ctx, generated_function);
|
instruction->gen_llvm(ctx, generated_function);
|
||||||
|
@ -56,7 +55,11 @@ void definition_defn::gen_llvm_second(llvm_context& ctx) {
|
||||||
ctx.builder.CreateRetVoid();
|
ctx.builder.CreateRetVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_data::typecheck_first(type_mgr& mgr, type_env& env) {
|
void definition_data::insert_types(type_mgr& mgr, type_env_ptr& env) {
|
||||||
|
this->env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
void definition_data::insert_constructors() const {
|
||||||
type_data* this_type = new type_data(name);
|
type_data* this_type = new type_data(name);
|
||||||
type_ptr return_type = type_ptr(this_type);
|
type_ptr return_type = type_ptr(this_type);
|
||||||
int next_tag = 0;
|
int next_tag = 0;
|
||||||
|
@ -71,19 +74,11 @@ void definition_data::typecheck_first(type_mgr& mgr, type_env& env) {
|
||||||
full_type = type_ptr(new type_arr(type, full_type));
|
full_type = type_ptr(new type_arr(type, full_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
env.bind(constructor->name, full_type);
|
env->bind(constructor->name, full_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const {
|
void definition_data::generate_llvm(llvm_context& ctx) {
|
||||||
// Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void definition_data::compile() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void definition_data::gen_llvm_first(llvm_context& ctx) {
|
|
||||||
for(auto& constructor : constructors) {
|
for(auto& constructor : constructors) {
|
||||||
auto new_function =
|
auto new_function =
|
||||||
ctx.create_custom_function(constructor->name, constructor->types.size());
|
ctx.create_custom_function(constructor->name, constructor->types.size());
|
||||||
|
@ -99,7 +94,3 @@ void definition_data::gen_llvm_first(llvm_context& ctx) {
|
||||||
ctx.builder.CreateRetVoid();
|
ctx.builder.CreateRetVoid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_data::gen_llvm_second(llvm_context& ctx) {
|
|
||||||
// Nothing
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
#include "instruction.hpp"
|
#include "instruction.hpp"
|
||||||
#include "llvm_context.hpp"
|
#include "llvm_context.hpp"
|
||||||
#include "type_env.hpp"
|
#include "type_env.hpp"
|
||||||
|
@ -8,18 +9,6 @@
|
||||||
struct ast;
|
struct ast;
|
||||||
using ast_ptr = std::unique_ptr<ast>;
|
using ast_ptr = std::unique_ptr<ast>;
|
||||||
|
|
||||||
struct definition {
|
|
||||||
virtual ~definition() = default;
|
|
||||||
|
|
||||||
virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0;
|
|
||||||
virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0;
|
|
||||||
virtual void compile() = 0;
|
|
||||||
virtual void gen_llvm_first(llvm_context& ctx) = 0;
|
|
||||||
virtual void gen_llvm_second(llvm_context& ctx) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
using definition_ptr = std::unique_ptr<definition>;
|
|
||||||
|
|
||||||
struct constructor {
|
struct constructor {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> types;
|
std::vector<std::string> types;
|
||||||
|
@ -31,13 +20,16 @@ struct constructor {
|
||||||
|
|
||||||
using constructor_ptr = std::unique_ptr<constructor>;
|
using constructor_ptr = std::unique_ptr<constructor>;
|
||||||
|
|
||||||
struct definition_defn : public definition {
|
struct definition_defn {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> params;
|
std::vector<std::string> params;
|
||||||
ast_ptr body;
|
ast_ptr body;
|
||||||
|
|
||||||
|
type_env_ptr env;
|
||||||
|
type_env_ptr var_env;
|
||||||
|
std::set<std::string> free_variables;
|
||||||
|
type_ptr full_type;
|
||||||
type_ptr return_type;
|
type_ptr return_type;
|
||||||
std::vector<type_ptr> param_types;
|
|
||||||
|
|
||||||
std::vector<instruction_ptr> instructions;
|
std::vector<instruction_ptr> instructions;
|
||||||
|
|
||||||
|
@ -48,23 +40,28 @@ struct definition_defn : public definition {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void typecheck_first(type_mgr& mgr, type_env& env);
|
void find_free(type_mgr& mgr, type_env_ptr& env);
|
||||||
void typecheck_second(type_mgr& mgr, const type_env& env) const;
|
void insert_types(type_mgr& mgr);
|
||||||
|
void typecheck(type_mgr& mgr);
|
||||||
void compile();
|
void compile();
|
||||||
void gen_llvm_first(llvm_context& ctx);
|
void declare_llvm(llvm_context& ctx);
|
||||||
void gen_llvm_second(llvm_context& ctx);
|
void generate_llvm(llvm_context& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct definition_data : public definition {
|
using definition_defn_ptr = std::unique_ptr<definition_defn>;
|
||||||
|
|
||||||
|
struct definition_data {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<constructor_ptr> constructors;
|
std::vector<constructor_ptr> constructors;
|
||||||
|
|
||||||
|
type_env_ptr env;
|
||||||
|
|
||||||
definition_data(std::string n, std::vector<constructor_ptr> cs)
|
definition_data(std::string n, std::vector<constructor_ptr> cs)
|
||||||
: name(std::move(n)), constructors(std::move(cs)) {}
|
: name(std::move(n)), constructors(std::move(cs)) {}
|
||||||
|
|
||||||
void typecheck_first(type_mgr& mgr, type_env& env);
|
void insert_types(type_mgr& mgr, type_env_ptr& env);
|
||||||
void typecheck_second(type_mgr& mgr, const type_env& env) const;
|
void insert_constructors() const;
|
||||||
void compile();
|
void generate_llvm(llvm_context& ctx);
|
||||||
void gen_llvm_first(llvm_context& ctx);
|
|
||||||
void gen_llvm_second(llvm_context& ctx);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using definition_data_ptr = std::unique_ptr<definition_data>;
|
||||||
|
|
81
10/main.cpp
81
10/main.cpp
|
@ -20,43 +20,52 @@ void yy::parser::error(const std::string& msg) {
|
||||||
std::cout << "An error occured: " << msg << std::endl;
|
std::cout << "An error occured: " << msg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::vector<definition_ptr> program;
|
extern std::vector<definition_data_ptr> defs_data;
|
||||||
|
extern std::vector<definition_defn_ptr> defs_defn;
|
||||||
|
|
||||||
void typecheck_program(
|
void typecheck_program(
|
||||||
const std::vector<definition_ptr>& prog,
|
const std::vector<definition_data_ptr>& defs_data,
|
||||||
type_mgr& mgr, type_env& env) {
|
const std::vector<definition_defn_ptr>& defs_defn,
|
||||||
|
type_mgr& mgr, type_env_ptr& env) {
|
||||||
type_ptr int_type = type_ptr(new type_base("Int"));
|
type_ptr int_type = type_ptr(new type_base("Int"));
|
||||||
type_ptr binop_type = type_ptr(new type_arr(
|
type_ptr binop_type = type_ptr(new type_arr(
|
||||||
int_type,
|
int_type,
|
||||||
type_ptr(new type_arr(int_type, int_type))));
|
type_ptr(new type_arr(int_type, int_type))));
|
||||||
|
|
||||||
env.bind("+", binop_type);
|
env->bind("+", binop_type);
|
||||||
env.bind("-", binop_type);
|
env->bind("-", binop_type);
|
||||||
env.bind("*", binop_type);
|
env->bind("*", binop_type);
|
||||||
env.bind("/", binop_type);
|
env->bind("/", binop_type);
|
||||||
|
|
||||||
for(auto& def : prog) {
|
for(auto& def_data : defs_data) {
|
||||||
def->typecheck_first(mgr, env);
|
def_data->insert_types(mgr, env);
|
||||||
|
}
|
||||||
|
for(auto& def_data : defs_data) {
|
||||||
|
def_data->insert_constructors();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& def : prog) {
|
for(auto& def_defn : defs_defn) {
|
||||||
def->typecheck_second(mgr, env);
|
def_defn->find_free(mgr, env);
|
||||||
|
}
|
||||||
|
for(auto& def_defn : defs_defn) {
|
||||||
|
def_defn->insert_types(mgr);
|
||||||
|
}
|
||||||
|
for(auto& def_defn : defs_defn) {
|
||||||
|
def_defn->typecheck(mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& pair : env.names) {
|
for(auto& pair : env->names) {
|
||||||
std::cout << pair.first << ": ";
|
std::cout << pair.first << ": ";
|
||||||
pair.second->print(mgr, std::cout);
|
pair.second->print(mgr, std::cout);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_program(const std::vector<definition_ptr>& prog) {
|
void compile_program(const std::vector<definition_defn_ptr>& defs_defn) {
|
||||||
for(auto& def : prog) {
|
for(auto& def_defn : defs_defn) {
|
||||||
def->compile();
|
def_defn->compile();
|
||||||
|
|
||||||
definition_defn* defn = dynamic_cast<definition_defn*>(def.get());
|
for(auto& instruction : def_defn->instructions) {
|
||||||
if(!defn) continue;
|
|
||||||
for(auto& instruction : defn->instructions) {
|
|
||||||
instruction->print(0, std::cout);
|
instruction->print(0, std::cout);
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
@ -120,20 +129,25 @@ void output_llvm(llvm_context& ctx, const std::string& filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_llvm(const std::vector<definition_ptr>& prog) {
|
void gen_llvm(
|
||||||
|
const std::vector<definition_data_ptr>& defs_data,
|
||||||
|
const std::vector<definition_defn_ptr>& defs_defn) {
|
||||||
llvm_context ctx;
|
llvm_context ctx;
|
||||||
gen_llvm_internal_op(ctx, PLUS);
|
gen_llvm_internal_op(ctx, PLUS);
|
||||||
gen_llvm_internal_op(ctx, MINUS);
|
gen_llvm_internal_op(ctx, MINUS);
|
||||||
gen_llvm_internal_op(ctx, TIMES);
|
gen_llvm_internal_op(ctx, TIMES);
|
||||||
gen_llvm_internal_op(ctx, DIVIDE);
|
gen_llvm_internal_op(ctx, DIVIDE);
|
||||||
|
|
||||||
for(auto& definition : prog) {
|
for(auto& def_data : defs_data) {
|
||||||
definition->gen_llvm_first(ctx);
|
def_data->generate_llvm(ctx);
|
||||||
|
}
|
||||||
|
for(auto& def_defn : defs_defn) {
|
||||||
|
def_defn->declare_llvm(ctx);
|
||||||
|
}
|
||||||
|
for(auto& def_defn : defs_defn) {
|
||||||
|
def_defn->generate_llvm(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& definition : prog) {
|
|
||||||
definition->gen_llvm_second(ctx);
|
|
||||||
}
|
|
||||||
ctx.module.print(llvm::outs(), nullptr);
|
ctx.module.print(llvm::outs(), nullptr);
|
||||||
output_llvm(ctx, "program.o");
|
output_llvm(ctx, "program.o");
|
||||||
}
|
}
|
||||||
|
@ -141,23 +155,20 @@ void gen_llvm(const std::vector<definition_ptr>& prog) {
|
||||||
int main() {
|
int main() {
|
||||||
yy::parser parser;
|
yy::parser parser;
|
||||||
type_mgr mgr;
|
type_mgr mgr;
|
||||||
type_env env;
|
type_env_ptr env(new type_env);
|
||||||
|
|
||||||
parser.parse();
|
parser.parse();
|
||||||
for(auto& definition : program) {
|
for(auto& def_defn : defs_defn) {
|
||||||
definition_defn* def = dynamic_cast<definition_defn*>(definition.get());
|
std::cout << def_defn->name;
|
||||||
if(!def) continue;
|
for(auto& param : def_defn->params) std::cout << " " << param;
|
||||||
|
|
||||||
std::cout << def->name;
|
|
||||||
for(auto& param : def->params) std::cout << " " << param;
|
|
||||||
std::cout << ":" << std::endl;
|
std::cout << ":" << std::endl;
|
||||||
|
|
||||||
def->body->print(1, std::cout);
|
def_defn->body->print(1, std::cout);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
typecheck_program(program, mgr, env);
|
typecheck_program(defs_data, defs_defn, mgr, env);
|
||||||
compile_program(program);
|
compile_program(defs_defn);
|
||||||
gen_llvm(program);
|
gen_llvm(defs_data, defs_defn);
|
||||||
} catch(unification_error& err) {
|
} catch(unification_error& err) {
|
||||||
std::cout << "failed to unify types: " << std::endl;
|
std::cout << "failed to unify types: " << std::endl;
|
||||||
std::cout << " (1) \033[34m";
|
std::cout << " (1) \033[34m";
|
||||||
|
|
22
10/parser.y
22
10/parser.y
|
@ -5,7 +5,9 @@
|
||||||
#include "definition.hpp"
|
#include "definition.hpp"
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
|
|
||||||
std::vector<definition_ptr> program;
|
std::vector<definition_data_ptr> defs_data;
|
||||||
|
std::vector<definition_defn_ptr> defs_defn;
|
||||||
|
|
||||||
extern yy::parser::symbol_type yylex();
|
extern yy::parser::symbol_type yylex();
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
@ -34,11 +36,11 @@ extern yy::parser::symbol_type yylex();
|
||||||
%define api.token.constructor
|
%define api.token.constructor
|
||||||
|
|
||||||
%type <std::vector<std::string>> lowercaseParams uppercaseParams
|
%type <std::vector<std::string>> lowercaseParams uppercaseParams
|
||||||
%type <std::vector<definition_ptr>> program definitions
|
|
||||||
%type <std::vector<branch_ptr>> branches
|
%type <std::vector<branch_ptr>> branches
|
||||||
%type <std::vector<constructor_ptr>> constructors
|
%type <std::vector<constructor_ptr>> constructors
|
||||||
%type <ast_ptr> aAdd aMul case app appBase
|
%type <ast_ptr> aAdd aMul case app appBase
|
||||||
%type <definition_ptr> definition defn data
|
%type <definition_data_ptr> data
|
||||||
|
%type <definition_defn_ptr> defn
|
||||||
%type <branch_ptr> branch
|
%type <branch_ptr> branch
|
||||||
%type <pattern_ptr> pattern
|
%type <pattern_ptr> pattern
|
||||||
%type <constructor_ptr> constructor
|
%type <constructor_ptr> constructor
|
||||||
|
@ -48,22 +50,22 @@ extern yy::parser::symbol_type yylex();
|
||||||
%%
|
%%
|
||||||
|
|
||||||
program
|
program
|
||||||
: definitions { program = std::move($1); }
|
: definitions { }
|
||||||
;
|
;
|
||||||
|
|
||||||
definitions
|
definitions
|
||||||
: definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); }
|
: definitions definition { }
|
||||||
| definition { $$ = std::vector<definition_ptr>(); $$.push_back(std::move($1)); }
|
| definition { }
|
||||||
;
|
;
|
||||||
|
|
||||||
definition
|
definition
|
||||||
: defn { $$ = std::move($1); }
|
: defn { defs_defn.push_back(std::move($1)); }
|
||||||
| data { $$ = std::move($1); }
|
| data { defs_data.push_back(std::move($1)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
defn
|
defn
|
||||||
: DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY
|
: DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY
|
||||||
{ $$ = definition_ptr(
|
{ $$ = definition_defn_ptr(
|
||||||
new definition_defn(std::move($2), std::move($3), std::move($6))); }
|
new definition_defn(std::move($2), std::move($3), std::move($6))); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -125,7 +127,7 @@ pattern
|
||||||
|
|
||||||
data
|
data
|
||||||
: DATA UID EQUAL OCURLY constructors CCURLY
|
: DATA UID EQUAL OCURLY constructors CCURLY
|
||||||
{ $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); }
|
{ $$ = definition_data_ptr(new definition_data(std::move($2), std::move($5))); }
|
||||||
;
|
;
|
||||||
|
|
||||||
constructors
|
constructors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user