diff --git a/programs/eq.lily b/programs/eq.lily new file mode 100644 index 0000000..49a6471 --- /dev/null +++ b/programs/eq.lily @@ -0,0 +1,6 @@ +defn main = { + case eq 1 1 of { + True -> { 326 } + False -> { 404 } + } +} diff --git a/programs/not.lily b/programs/not.lily index 7b2bf4b..cc0376e 100644 --- a/programs/not.lily +++ b/programs/not.lily @@ -1,4 +1,3 @@ -data Bool = { True, False } defn not b = { case b of { False -> { True } diff --git a/src/gmachine.cpp b/src/gmachine.cpp index 4becc62..ec454bb 100644 --- a/src/gmachine.cpp +++ b/src/gmachine.cpp @@ -62,6 +62,11 @@ namespace lily { return os; } + std::ostream& instruction_eq::to_stream(std::ostream& os) { + os << "eq"; + return os; + } + std::ostream& instruction_cond::to_stream(std::ostream& os) { os << "cond"; return os; @@ -166,6 +171,39 @@ namespace lily { 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) { } diff --git a/src/gmachine.hpp b/src/gmachine.hpp index e37c4d7..d702ccc 100644 --- a/src/gmachine.hpp +++ b/src/gmachine.hpp @@ -94,6 +94,11 @@ namespace lily { 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 { std::vector true_branch; std::vector false_branch; diff --git a/src/parser.cpp b/src/parser.cpp index 62f61ab..6af2e32 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -246,6 +246,13 @@ namespace lily { return prog; } + program::program() { + type_data* data = type_mgr.create_data_type("Bool"); + std::vector params; + data->create_constructor("True", std::move(params)); + data->create_constructor("False", std::move(params)); + } + void program::check() { // Each function has an environment, which will be used // as base for type checking. @@ -281,6 +288,13 @@ namespace lily { 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(eq_param_type, eq_return_type); + type* eq_app_2 = type_mgr.create_type(eq_param_type, eq_app_1); + base_env->set_type("eq", eq_app_2); + // We also want to gather all the constructor calls. type_mgr.register_constructors(base_env); @@ -311,6 +325,16 @@ namespace lily { generate_binop(mgr, into); generate_binop(mgr, into); generate_binop(mgr, into); + + std::vector dest; + dest.push_back(mgr.add_instruction(1)); + dest.push_back(mgr.add_instruction()); + dest.push_back(mgr.add_instruction(1)); + dest.push_back(mgr.add_instruction()); + dest.push_back(mgr.add_instruction()); + dest.push_back(mgr.add_instruction(2)); + dest.push_back(mgr.add_instruction(2)); + into["eq"] = std::move(dest); } void program::compile(instruction_manager& mgr, std::map>& into) { diff --git a/src/parser.hpp b/src/parser.hpp index 5f8d0d9..86b20ab 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -13,6 +13,8 @@ namespace lily { type_manager type_mgr; std::map functions; + program(); + void check(); void compile(instruction_manager& mgr, std::map>& into); void gen_llvm();