diff --git a/code/compiler/13/ast.cpp b/code/compiler/13/ast.cpp index 8a99486..2ad9d04 100644 --- a/code/compiler/13/ast.cpp +++ b/code/compiler/13/ast.cpp @@ -228,8 +228,6 @@ struct case_mappings { std::optional> default_case; std::vector& make_case_for(tag_type tag) { - auto existing_case = defined_cases.find(tag); - if(existing_case != defined_cases.end()) return existing_case->second; if(default_case) throw type_error("attempted pattern match after catch-all"); return defined_cases[tag]; @@ -279,7 +277,9 @@ struct case_strategy_bool { if(!(cpat = dynamic_cast(pt.get())) || (cpat->constr != "True" && cpat->constr != "False") || cpat->params.size() != 0) - throw type_error("pattern cannot be converted to a boolean"); + throw type_error( + "pattern cannot be converted to a boolean", + pt->loc); return cpat->constr == "True"; } @@ -321,7 +321,9 @@ struct case_strategy_data { repr_type from_typed_pattern(const pattern_ptr& pt, const type* type) { pattern_constr* cpat; if(!(cpat = dynamic_cast(pt.get()))) - throw type_error("pattern cannot be interpreted as constructor."); + throw type_error( + "pattern cannot be interpreted as constructor.", + pt->loc); return std::make_pair( &static_cast(type)->constructors.find(cpat->constr)->second, &cpat->params); @@ -383,6 +385,8 @@ void compile_case(const ast_case& node, const env_ptr& env, const type* type, st for(auto& branch : node.branches) { pattern_var* vpat; if((vpat = dynamic_cast(branch->pat.get()))) { + if(cases.defined_cases_count() == strategy.case_count(type)) + throw type_error("redundant catch-all pattern", branch->pat->loc); auto& branch_into = cases.make_default_case(); env_ptr new_env(new env_var(branch->expr->env->get_mangled_name(vpat->var), env)); branch->expr->compile(new_env, branch_into); @@ -589,5 +593,5 @@ void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) con constructor_type = arr->right; } - mgr.unify(constructor_type, t, loc); + mgr.unify(t, constructor_type, loc); }