diff --git a/code/compiler/13/ast.cpp b/code/compiler/13/ast.cpp index 7efe9b1..1f1eb31 100644 --- a/code/compiler/13/ast.cpp +++ b/code/compiler/13/ast.cpp @@ -3,6 +3,7 @@ #include #include "binop.hpp" #include "error.hpp" +#include "type.hpp" #include "type_env.hpp" #include "env.hpp" @@ -275,9 +276,11 @@ struct case_strategy_bool { using tag_type = bool; using repr_type = bool; + case_strategy_bool(const type* type) {} + tag_type tag_from_repr(repr_type b) { return b; } - repr_type from_typed_pattern(const pattern_ptr& pt, const type* type) { + repr_type repr_from_pattern(const pattern_ptr& pt) { pattern_constr* cpat; if(!(cpat = dynamic_cast(pt.get())) || (cpat->constr != "True" && cpat->constr != "False") || @@ -297,12 +300,11 @@ struct case_strategy_bool { into.push_back(instruction_ptr(new instruction_slide(1))); } - size_t case_count(const type* type) { + size_t case_count() { return 2; } void into_instructions( - const type* type, case_mappings& ms, std::vector& into) { if(ms.defined_cases_count() == 0) { @@ -321,16 +323,23 @@ struct case_strategy_data { using tag_type = int; using repr_type = std::pair*>; + const type_data* arg_type; + + case_strategy_data(const type* t) { + arg_type = dynamic_cast(t); + assert(arg_type); + } + tag_type tag_from_repr(const repr_type& repr) { return repr.first->tag; } - repr_type from_typed_pattern(const pattern_ptr& pt, const type* type) { + repr_type repr_from_pattern(const pattern_ptr& pt) { pattern_constr* cpat; if(!(cpat = dynamic_cast(pt.get()))) throw type_error( "pattern cannot be interpreted as constructor.", pt->loc); return std::make_pair( - &static_cast(type)->constructors.find(cpat->constr)->second, + &arg_type->constructors.find(cpat->constr)->second, &cpat->params); } @@ -349,19 +358,17 @@ struct case_strategy_data { into.push_back(instruction_ptr(new instruction_slide(repr.second->size()))); } - size_t case_count(const type* type) { - return static_cast(type)->constructors.size(); + size_t case_count() { + return arg_type->constructors.size(); } void into_instructions( - const type* type, case_mappings& ms, std::vector& into) { instruction_jump* jump_instruction = new instruction_jump(); instruction_ptr inst(jump_instruction); - auto data_type = static_cast(type); - for(auto& constr : data_type->constructors) { + for(auto& constr : arg_type->constructors) { if(!ms.case_defined_for(constr.second.tag)) continue; jump_instruction->branches.push_back( std::move(ms.get_specific_case_for(constr.second.tag))); @@ -372,7 +379,7 @@ struct case_strategy_data { if(ms.default_case_defined()) { jump_instruction->branches.push_back( std::move(ms.get_default_case())); - for(auto& constr : data_type->constructors) { + for(auto& constr : arg_type->constructors) { if(ms.case_defined_for(constr.second.tag)) continue; jump_instruction->tag_mappings[constr.second.tag] = jump_instruction->branches.size(); @@ -385,29 +392,29 @@ struct case_strategy_data { template void compile_case(const ast_case& node, const env_ptr& env, const type* type, std::vector& into) { - T strategy; + T strategy(type); case_mappings cases; for(auto& branch : node.branches) { pattern_var* vpat; if((vpat = dynamic_cast(branch->pat.get()))) { - if(cases.defined_cases_count() == strategy.case_count(type)) + if(cases.defined_cases_count() == strategy.case_count()) throw type_error("redundant catch-all pattern", branch->pat->loc); auto& branch_into = cases.make_default_case(); env_ptr new_env(new env_var(vpat->var, env)); branch->expr->compile(new_env, branch_into); branch_into.push_back(instruction_ptr(new instruction_slide(1))); } else { - auto repr = strategy.from_typed_pattern(branch->pat, type); + auto repr = strategy.repr_from_pattern(branch->pat); auto& branch_into = cases.make_case_for(strategy.tag_from_repr(repr)); strategy.compile_branch(branch, env, repr, branch_into); } } - if(!(cases.defined_cases_count() == strategy.case_count(type) || + if(!(cases.defined_cases_count() == strategy.case_count() || cases.default_case_defined())) throw type_error("incomplete patterns", node.loc); - strategy.into_instructions(type, cases, into); + strategy.into_instructions(cases, into); } void ast_case::compile(const env_ptr& env, std::vector& into) const {