diff --git a/06/ast.cpp b/06/ast.cpp index 3954a8a..ad85a09 100644 --- a/06/ast.cpp +++ b/06/ast.cpp @@ -176,7 +176,51 @@ void ast_case::resolve(const type_mgr& mgr) const { } void ast_case::compile(const env_ptr& env, std::vector& into) const { + type_data* type = dynamic_cast(node_type.get()); + of->compile(env, into); + into.push_back(instruction_ptr(new instruction_eval())); + + instruction_jump* jump_instruction = new instruction_jump(); + into.push_back(instruction_ptr(jump_instruction)); + for(auto& branch : branches) { + std::vector branch_instructions; + pattern_var* vpat; + pattern_constr* cpat; + + if((vpat = dynamic_cast(branch->pat.get()))) { + branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); + + for(auto& constr_pair : type->constructors) { + if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != + jump_instruction->tag_mappings.end()) + break; + + jump_instruction->tag_mappings[constr_pair.second.tag] = + jump_instruction->branches.size(); + } + jump_instruction->branches.push_back(std::move(branch_instructions)); + } else if((cpat = dynamic_cast(branch->pat.get()))) { + branch_instructions.push_back(instruction_ptr(new instruction_split())); + branch->expr->compile(env_ptr(new env_offset(cpat->params.size(), env)), + branch_instructions); + + int new_tag = type->constructors[cpat->constr].tag; + if(jump_instruction->tag_mappings.find(new_tag) != + jump_instruction->tag_mappings.end()) + throw type_error("technically not a type error: duplicate pattern"); + + jump_instruction->tag_mappings[new_tag] = + jump_instruction->branches.size(); + jump_instruction->branches.push_back(std::move(branch_instructions)); + } + } + + for(auto& constr_pair : type->constructors) { + if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == + jump_instruction->tag_mappings.end()) + throw type_error("non-total pattern"); + } } void pattern_var::print(std::ostream& to) const { diff --git a/06/instruction.hpp b/06/instruction.hpp index 8d846e0..40196e4 100644 --- a/06/instruction.hpp +++ b/06/instruction.hpp @@ -2,6 +2,8 @@ #include #include #include "binop.hpp" +#include +#include struct instruction { virtual ~instruction() = default; @@ -53,6 +55,11 @@ struct instruction_split : public instruction { }; +struct instruction_jump : public instruction { + std::vector> branches; + std::map tag_mappings; +}; + struct instruction_slide : public instruction { int offset;