Clumsily add equality checking.

This commit is contained in:
Danila Fedorin 2019-06-12 19:27:52 -07:00
parent 9855dda31a
commit df33263fcd
6 changed files with 75 additions and 1 deletions

6
programs/eq.lily Normal file
View File

@ -0,0 +1,6 @@
defn main = {
case eq 1 1 of {
True -> { 326 }
False -> { 404 }
}
}

View File

@ -1,4 +1,3 @@
data Bool = { True, False }
defn not b = { defn not b = {
case b of { case b of {
False -> { True } False -> { True }

View File

@ -62,6 +62,11 @@ namespace lily {
return os; return os;
} }
std::ostream& instruction_eq::to_stream(std::ostream& os) {
os << "eq";
return os;
}
std::ostream& instruction_cond::to_stream(std::ostream& os) { std::ostream& instruction_cond::to_stream(std::ostream& os) {
os << "cond"; os << "cond";
return os; return os;
@ -166,6 +171,39 @@ namespace lily {
builder.CreateCall(stack_push_func, { stack, new_node }); builder.CreateCall(stack_push_func, { stack, new_node });
} }
void instruction_eq::gen_llvm(llvm_context& ctx) {
llvm::Value* stack = ctx.get_current_function()->arg_begin();
llvm::Value* param2 = builder.CreateCall(stack_pop_func, { stack }, "temp");
llvm::Value* param1 = builder.CreateCall(stack_pop_func, { stack }, "temp");
llvm::Value* param1_node_num = builder.CreatePointerCast(param1, llvm::PointerType::getUnqual(node_num_type), "temp");
llvm::Value* param2_node_num = builder.CreatePointerCast(param2, llvm::PointerType::getUnqual(node_num_type), "temp");
llvm::Value* param1_intptr = builder.CreateGEP(param1_node_num, { get_int32_constant(0), get_int32_constant(1) }, "temp");
llvm::Value* param2_intptr = builder.CreateGEP(param2_node_num, { get_int32_constant(0), get_int32_constant(1) }, "temp");
llvm::Value* param1_int = builder.CreateLoad(llvm::IntegerType::get(context, 32), param1_intptr, "temp");
llvm::Value* param2_int = builder.CreateLoad(llvm::IntegerType::get(context, 32), param2_intptr, "temp");
llvm::Value* compare_result = builder.CreateICmpEQ(param1_int, param2_int, "temp");
llvm::BasicBlock* false_block = llvm::BasicBlock::Create(context, "false", ctx.get_current_function());
llvm::BasicBlock* true_block = llvm::BasicBlock::Create(context, "true", ctx.get_current_function());
builder.CreateCondBr(compare_result, true_block, false_block);
llvm::BasicBlock* after = llvm::BasicBlock::Create(context, "after", ctx.get_current_function());
builder.SetInsertPoint(false_block);
llvm::Value* false_node = builder.CreateCall(malloc_node_global_func,
{ get_int8_constant(0), ctx.get_supercombinator_function("False") }, "temp");
builder.CreateCall(stack_push_func, { stack, false_node });
builder.CreateBr(after);
builder.SetInsertPoint(true_block);
llvm::Value* true_node = builder.CreateCall(malloc_node_global_func,
{ get_int8_constant(0), ctx.get_supercombinator_function("True") }, "temp");
builder.CreateCall(stack_push_func, { stack, true_node });
builder.CreateBr(after);
builder.SetInsertPoint(after);
}
void instruction_cond::gen_llvm(llvm_context& ctx) { void instruction_cond::gen_llvm(llvm_context& ctx) {
} }

View File

@ -94,6 +94,11 @@ namespace lily {
void gen_llvm(llvm_context& ctx); void gen_llvm(llvm_context& ctx);
}; };
struct instruction_eq : instruction {
std::ostream& to_stream(std::ostream& os);
void gen_llvm(llvm_context& ctx);
};
struct instruction_cond : instruction { struct instruction_cond : instruction {
std::vector<instruction*> true_branch; std::vector<instruction*> true_branch;
std::vector<instruction*> false_branch; std::vector<instruction*> false_branch;

View File

@ -246,6 +246,13 @@ namespace lily {
return prog; return prog;
} }
program::program() {
type_data* data = type_mgr.create_data_type("Bool");
std::vector<type*> params;
data->create_constructor("True", std::move(params));
data->create_constructor("False", std::move(params));
}
void program::check() { void program::check() {
// Each function has an environment, which will be used // Each function has an environment, which will be used
// as base for type checking. // as base for type checking.
@ -281,6 +288,13 @@ namespace lily {
base_env->set_type(pair.first, current_type); base_env->set_type(pair.first, current_type);
} }
// Also add internal functions
type* eq_return_type = type_mgr.require_type("Bool");
type* eq_param_type = type_mgr.require_type("Int");
type* eq_app_1 = type_mgr.create_type<type_func>(eq_param_type, eq_return_type);
type* eq_app_2 = type_mgr.create_type<type_func>(eq_param_type, eq_app_1);
base_env->set_type("eq", eq_app_2);
// We also want to gather all the constructor calls. // We also want to gather all the constructor calls.
type_mgr.register_constructors(base_env); type_mgr.register_constructors(base_env);
@ -311,6 +325,16 @@ namespace lily {
generate_binop<binop::subtract>(mgr, into); generate_binop<binop::subtract>(mgr, into);
generate_binop<binop::times>(mgr, into); generate_binop<binop::times>(mgr, into);
generate_binop<binop::divide>(mgr, into); generate_binop<binop::divide>(mgr, into);
std::vector<instruction*> dest;
dest.push_back(mgr.add_instruction<instruction_push>(1));
dest.push_back(mgr.add_instruction<instruction_eval>());
dest.push_back(mgr.add_instruction<instruction_push>(1));
dest.push_back(mgr.add_instruction<instruction_eval>());
dest.push_back(mgr.add_instruction<instruction_eq>());
dest.push_back(mgr.add_instruction<instruction_update>(2));
dest.push_back(mgr.add_instruction<instruction_pop>(2));
into["eq"] = std::move(dest);
} }
void program::compile(instruction_manager& mgr, std::map<std::string, std::vector<instruction*>>& into) { void program::compile(instruction_manager& mgr, std::map<std::string, std::vector<instruction*>>& into) {

View File

@ -13,6 +13,8 @@ namespace lily {
type_manager type_mgr; type_manager type_mgr;
std::map<std::string, function> functions; std::map<std::string, function> functions;
program();
void check(); void check();
void compile(instruction_manager& mgr, std::map<std::string, std::vector<instruction*>>& into); void compile(instruction_manager& mgr, std::map<std::string, std::vector<instruction*>>& into);
void gen_llvm(); void gen_llvm();