|
|
|
@ -22,13 +22,15 @@ void yy::parser::error(const yy::location& loc, const std::string& msg) { |
|
|
|
|
std::cout << "An error occured: " << msg << std::endl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void typecheck_program( |
|
|
|
|
definition_group& defs, |
|
|
|
|
type_mgr& mgr, type_env_ptr& env) { |
|
|
|
|
void prelude_types(definition_group& defs, type_env_ptr env) { |
|
|
|
|
type_ptr int_type = type_ptr(new type_internal("Int"));
|
|
|
|
|
env->bind_type("Int", int_type); |
|
|
|
|
type_ptr int_type_app = type_ptr(new type_app(int_type)); |
|
|
|
|
|
|
|
|
|
type_ptr bool_type = type_ptr(new type_internal("Bool")); |
|
|
|
|
env->bind_type("Bool", bool_type); |
|
|
|
|
type_ptr bool_type_app = type_ptr(new type_app(bool_type)); |
|
|
|
|
|
|
|
|
|
type_ptr binop_type = type_ptr(new type_arr( |
|
|
|
|
int_type_app, |
|
|
|
|
type_ptr(new type_arr(int_type_app, int_type_app)))); |
|
|
|
@ -37,6 +39,15 @@ void typecheck_program( |
|
|
|
|
env->bind("*", binop_type, visibility::global); |
|
|
|
|
env->bind("/", binop_type, visibility::global); |
|
|
|
|
|
|
|
|
|
env->bind("True", bool_type_app, visibility::global); |
|
|
|
|
env->bind("False", bool_type_app, visibility::global); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void typecheck_program( |
|
|
|
|
definition_group& defs, |
|
|
|
|
type_mgr& mgr, type_env_ptr& env) { |
|
|
|
|
prelude_types(defs, env); |
|
|
|
|
|
|
|
|
|
std::set<std::string> free; |
|
|
|
|
defs.find_free(free); |
|
|
|
|
defs.typecheck(mgr, env); |
|
|
|
@ -60,23 +71,6 @@ global_scope translate_program(definition_group& group) { |
|
|
|
|
return scope; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void gen_llvm_internal_op(llvm_context& ctx, binop op) { |
|
|
|
|
auto new_function = ctx.create_custom_function(op_action(op), 2); |
|
|
|
|
std::vector<instruction_ptr> instructions; |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_push(1))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_eval())); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_push(1))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_eval())); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_binop(op))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_update(2))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_pop(2))); |
|
|
|
|
ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); |
|
|
|
|
for(auto& instruction : instructions) { |
|
|
|
|
instruction->gen_llvm(ctx, new_function); |
|
|
|
|
} |
|
|
|
|
ctx.builder.CreateRetVoid(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void output_llvm(llvm_context& ctx, const std::string& filename) { |
|
|
|
|
std::string targetTriple = llvm::sys::getDefaultTargetTriple(); |
|
|
|
|
|
|
|
|
@ -117,12 +111,43 @@ void output_llvm(llvm_context& ctx, const std::string& filename) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void gen_llvm_internal_op(llvm_context& ctx, binop op) { |
|
|
|
|
auto new_function = ctx.create_custom_function(op_action(op), 2); |
|
|
|
|
std::vector<instruction_ptr> instructions; |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_push(1))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_eval())); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_push(1))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_eval())); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_binop(op))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_update(2))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_pop(2))); |
|
|
|
|
ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); |
|
|
|
|
for(auto& instruction : instructions) { |
|
|
|
|
instruction->gen_llvm(ctx, new_function); |
|
|
|
|
} |
|
|
|
|
ctx.builder.CreateRetVoid(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void gen_llvm_boolean_constructor(llvm_context& ctx, const std::string& s, bool b) { |
|
|
|
|
auto new_function = ctx.create_custom_function(s, 0); |
|
|
|
|
std::vector<instruction_ptr> instructions; |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_pushint(b))); |
|
|
|
|
instructions.push_back(instruction_ptr(new instruction_update(0))); |
|
|
|
|
ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); |
|
|
|
|
for(auto& instruction : instructions) { |
|
|
|
|
instruction->gen_llvm(ctx, new_function); |
|
|
|
|
} |
|
|
|
|
ctx.builder.CreateRetVoid(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void gen_llvm(global_scope& scope) { |
|
|
|
|
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); |
|
|
|
|
gen_llvm_boolean_constructor(ctx, "True", true); |
|
|
|
|
gen_llvm_boolean_constructor(ctx, "False", false); |
|
|
|
|
|
|
|
|
|
scope.generate_llvm(ctx); |
|
|
|
|
|
|
|
|
|