Separate definitions in compiler series
This commit is contained in:
parent
6714e18e7c
commit
0efa05142f
|
@ -2,6 +2,7 @@
|
|||
#include <ostream>
|
||||
#include "binop.hpp"
|
||||
#include "error.hpp"
|
||||
#include "type_env.hpp"
|
||||
|
||||
static void print_indent(int n, std::ostream& to) {
|
||||
while(n--) to << " ";
|
||||
|
@ -12,7 +13,11 @@ void ast_int::print(int indent, std::ostream& to) const {
|
|||
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"));
|
||||
}
|
||||
|
||||
|
@ -25,8 +30,13 @@ void ast_lid::print(int indent, std::ostream& to) const {
|
|||
to << "LID: " << id << std::endl;
|
||||
}
|
||||
|
||||
type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) {
|
||||
return env.lookup(id);
|
||||
void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set<std::string>& into) {
|
||||
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 {
|
||||
|
@ -41,8 +51,12 @@ void ast_uid::print(int indent, std::ostream& to) const {
|
|||
to << "UID: " << id << std::endl;
|
||||
}
|
||||
|
||||
type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) {
|
||||
return env.lookup(id);
|
||||
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) {
|
||||
return env->lookup(id);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) {
|
||||
type_ptr ltype = left->typecheck(mgr, env);
|
||||
type_ptr rtype = right->typecheck(mgr, env);
|
||||
type_ptr ftype = env.lookup(op_name(op));
|
||||
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_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));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) {
|
||||
type_ptr ltype = left->typecheck(mgr, env);
|
||||
type_ptr rtype = right->typecheck(mgr, env);
|
||||
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_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));
|
||||
|
@ -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_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 new_env = env.scope();
|
||||
branch->pat->match(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);
|
||||
}
|
||||
|
||||
|
@ -192,8 +227,12 @@ void pattern_var::print(std::ostream& to) const {
|
|||
to << var;
|
||||
}
|
||||
|
||||
void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const {
|
||||
env.bind(var, t);
|
||||
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 {
|
||||
mgr.unify(env->lookup(var), t);
|
||||
}
|
||||
|
||||
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 {
|
||||
type_ptr constructor_type = env.lookup(constr);
|
||||
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 {
|
||||
type_ptr constructor_type = env->lookup(constr);
|
||||
if(!constructor_type) {
|
||||
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());
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "type.hpp"
|
||||
#include "type_env.hpp"
|
||||
#include "binop.hpp"
|
||||
|
@ -8,10 +9,14 @@
|
|||
#include "env.hpp"
|
||||
|
||||
struct ast {
|
||||
type_env_ptr env;
|
||||
|
||||
virtual ~ast() = default;
|
||||
|
||||
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,
|
||||
std::vector<instruction_ptr>& into) const = 0;
|
||||
};
|
||||
|
@ -22,7 +27,8 @@ struct pattern {
|
|||
virtual ~pattern() = default;
|
||||
|
||||
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>;
|
||||
|
@ -44,7 +50,8 @@ struct ast_int : public ast {
|
|||
: value(v) {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -55,7 +62,8 @@ struct ast_lid : public ast {
|
|||
: id(std::move(i)) {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -66,7 +74,8 @@ struct ast_uid : public ast {
|
|||
: id(std::move(i)) {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -79,7 +88,8 @@ struct ast_binop : public ast {
|
|||
: op(o), left(std::move(l)), right(std::move(r)) {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -91,7 +101,8 @@ struct ast_app : public ast {
|
|||
: left(std::move(l)), right(std::move(r)) {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -104,7 +115,8 @@ struct ast_case : public ast {
|
|||
: of(std::move(o)), branches(std::move(b)) {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -115,7 +127,8 @@ struct pattern_var : public pattern {
|
|||
: var(std::move(v)) {}
|
||||
|
||||
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 {
|
||||
|
@ -126,5 +139,6 @@ struct pattern_constr : public pattern {
|
|||
: constr(std::move(c)), params(std::move(p)) {}
|
||||
|
||||
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 "instruction.hpp"
|
||||
#include "llvm_context.hpp"
|
||||
#include "type_env.hpp"
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/Function.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();
|
||||
type_ptr full_type = return_type;
|
||||
full_type = return_type;
|
||||
|
||||
for(auto it = params.rbegin(); it != params.rend(); it++) {
|
||||
type_ptr param_type = mgr.new_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 {
|
||||
type_env new_env = env.scope();
|
||||
auto param_it = params.begin();
|
||||
auto type_it = param_types.rbegin();
|
||||
void definition_defn::insert_types(type_mgr& mgr) {
|
||||
env->bind(name, full_type);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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_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());
|
||||
}
|
||||
|
||||
void definition_defn::gen_llvm_second(llvm_context& ctx) {
|
||||
void definition_defn::generate_llvm(llvm_context& ctx) {
|
||||
ctx.builder.SetInsertPoint(&generated_function->getEntryBlock());
|
||||
for(auto& instruction : instructions) {
|
||||
instruction->gen_llvm(ctx, generated_function);
|
||||
|
@ -56,7 +55,11 @@ void definition_defn::gen_llvm_second(llvm_context& ctx) {
|
|||
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_ptr return_type = type_ptr(this_type);
|
||||
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));
|
||||
}
|
||||
|
||||
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 {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
void definition_data::compile() {
|
||||
|
||||
}
|
||||
|
||||
void definition_data::gen_llvm_first(llvm_context& ctx) {
|
||||
void definition_data::generate_llvm(llvm_context& ctx) {
|
||||
for(auto& constructor : constructors) {
|
||||
auto new_function =
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void definition_data::gen_llvm_second(llvm_context& ctx) {
|
||||
// Nothing
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "instruction.hpp"
|
||||
#include "llvm_context.hpp"
|
||||
#include "type_env.hpp"
|
||||
|
@ -8,18 +9,6 @@
|
|||
struct 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 {
|
||||
std::string name;
|
||||
std::vector<std::string> types;
|
||||
|
@ -31,13 +20,16 @@ struct constructor {
|
|||
|
||||
using constructor_ptr = std::unique_ptr<constructor>;
|
||||
|
||||
struct definition_defn : public definition {
|
||||
struct definition_defn {
|
||||
std::string name;
|
||||
std::vector<std::string> params;
|
||||
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;
|
||||
std::vector<type_ptr> param_types;
|
||||
|
||||
std::vector<instruction_ptr> instructions;
|
||||
|
||||
|
@ -48,23 +40,28 @@ struct definition_defn : public definition {
|
|||
|
||||
}
|
||||
|
||||
void typecheck_first(type_mgr& mgr, type_env& env);
|
||||
void typecheck_second(type_mgr& mgr, const type_env& env) const;
|
||||
void find_free(type_mgr& mgr, type_env_ptr& env);
|
||||
void insert_types(type_mgr& mgr);
|
||||
void typecheck(type_mgr& mgr);
|
||||
void compile();
|
||||
void gen_llvm_first(llvm_context& ctx);
|
||||
void gen_llvm_second(llvm_context& ctx);
|
||||
void declare_llvm(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::vector<constructor_ptr> constructors;
|
||||
|
||||
type_env_ptr env;
|
||||
|
||||
definition_data(std::string n, std::vector<constructor_ptr> cs)
|
||||
: name(std::move(n)), constructors(std::move(cs)) {}
|
||||
|
||||
void typecheck_first(type_mgr& mgr, type_env& env);
|
||||
void typecheck_second(type_mgr& mgr, const type_env& env) const;
|
||||
void compile();
|
||||
void gen_llvm_first(llvm_context& ctx);
|
||||
void gen_llvm_second(llvm_context& ctx);
|
||||
void insert_types(type_mgr& mgr, type_env_ptr& env);
|
||||
void insert_constructors() const;
|
||||
void generate_llvm(llvm_context& ctx);
|
||||
};
|
||||
|
||||
using definition_data_ptr = std::unique_ptr<definition_data>;
|
||||
|
|
|
@ -20,43 +20,52 @@ void yy::parser::error(const std::string& msg) {
|
|||
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(
|
||||
const std::vector<definition_ptr>& prog,
|
||||
type_mgr& mgr, type_env& env) {
|
||||
const std::vector<definition_data_ptr>& defs_data,
|
||||
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 binop_type = type_ptr(new type_arr(
|
||||
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) {
|
||||
def->typecheck_first(mgr, env);
|
||||
for(auto& def_data : defs_data) {
|
||||
def_data->insert_types(mgr, env);
|
||||
}
|
||||
for(auto& def_data : defs_data) {
|
||||
def_data->insert_constructors();
|
||||
}
|
||||
|
||||
for(auto& def : prog) {
|
||||
def->typecheck_second(mgr, env);
|
||||
for(auto& def_defn : defs_defn) {
|
||||
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 << ": ";
|
||||
pair.second->print(mgr, std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void compile_program(const std::vector<definition_ptr>& prog) {
|
||||
for(auto& def : prog) {
|
||||
def->compile();
|
||||
void compile_program(const std::vector<definition_defn_ptr>& defs_defn) {
|
||||
for(auto& def_defn : defs_defn) {
|
||||
def_defn->compile();
|
||||
|
||||
definition_defn* defn = dynamic_cast<definition_defn*>(def.get());
|
||||
if(!defn) continue;
|
||||
for(auto& instruction : defn->instructions) {
|
||||
for(auto& instruction : def_defn->instructions) {
|
||||
instruction->print(0, std::cout);
|
||||
}
|
||||
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;
|
||||
gen_llvm_internal_op(ctx, PLUS);
|
||||
gen_llvm_internal_op(ctx, MINUS);
|
||||
gen_llvm_internal_op(ctx, TIMES);
|
||||
gen_llvm_internal_op(ctx, DIVIDE);
|
||||
|
||||
for(auto& definition : prog) {
|
||||
definition->gen_llvm_first(ctx);
|
||||
for(auto& def_data : defs_data) {
|
||||
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);
|
||||
output_llvm(ctx, "program.o");
|
||||
}
|
||||
|
@ -141,23 +155,20 @@ void gen_llvm(const std::vector<definition_ptr>& prog) {
|
|||
int main() {
|
||||
yy::parser parser;
|
||||
type_mgr mgr;
|
||||
type_env env;
|
||||
type_env_ptr env(new type_env);
|
||||
|
||||
parser.parse();
|
||||
for(auto& definition : program) {
|
||||
definition_defn* def = dynamic_cast<definition_defn*>(definition.get());
|
||||
if(!def) continue;
|
||||
|
||||
std::cout << def->name;
|
||||
for(auto& param : def->params) std::cout << " " << param;
|
||||
for(auto& def_defn : defs_defn) {
|
||||
std::cout << def_defn->name;
|
||||
for(auto& param : def_defn->params) std::cout << " " << param;
|
||||
std::cout << ":" << std::endl;
|
||||
|
||||
def->body->print(1, std::cout);
|
||||
def_defn->body->print(1, std::cout);
|
||||
}
|
||||
try {
|
||||
typecheck_program(program, mgr, env);
|
||||
compile_program(program);
|
||||
gen_llvm(program);
|
||||
typecheck_program(defs_data, defs_defn, mgr, env);
|
||||
compile_program(defs_defn);
|
||||
gen_llvm(defs_data, defs_defn);
|
||||
} catch(unification_error& err) {
|
||||
std::cout << "failed to unify types: " << std::endl;
|
||||
std::cout << " (1) \033[34m";
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#include "definition.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();
|
||||
|
||||
%}
|
||||
|
@ -34,11 +36,11 @@ extern yy::parser::symbol_type yylex();
|
|||
%define api.token.constructor
|
||||
|
||||
%type <std::vector<std::string>> lowercaseParams uppercaseParams
|
||||
%type <std::vector<definition_ptr>> program definitions
|
||||
%type <std::vector<branch_ptr>> branches
|
||||
%type <std::vector<constructor_ptr>> constructors
|
||||
%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 <pattern_ptr> pattern
|
||||
%type <constructor_ptr> constructor
|
||||
|
@ -48,22 +50,22 @@ extern yy::parser::symbol_type yylex();
|
|||
%%
|
||||
|
||||
program
|
||||
: definitions { program = std::move($1); }
|
||||
: definitions { }
|
||||
;
|
||||
|
||||
definitions
|
||||
: definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); }
|
||||
| definition { $$ = std::vector<definition_ptr>(); $$.push_back(std::move($1)); }
|
||||
: definitions definition { }
|
||||
| definition { }
|
||||
;
|
||||
|
||||
definition
|
||||
: defn { $$ = std::move($1); }
|
||||
| data { $$ = std::move($1); }
|
||||
: defn { defs_defn.push_back(std::move($1)); }
|
||||
| data { defs_data.push_back(std::move($1)); }
|
||||
;
|
||||
|
||||
defn
|
||||
: DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY
|
||||
{ $$ = definition_ptr(
|
||||
{ $$ = definition_defn_ptr(
|
||||
new definition_defn(std::move($2), std::move($3), std::move($6))); }
|
||||
;
|
||||
|
||||
|
@ -125,7 +127,7 @@ pattern
|
|||
|
||||
data
|
||||
: 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
|
||||
|
|
Loading…
Reference in New Issue
Block a user