diff --git a/code/compiler/13/definition.cpp b/code/compiler/13/definition.cpp index c6e69ae..dc36f20 100644 --- a/code/compiler/13/definition.cpp +++ b/code/compiler/13/definition.cpp @@ -1,4 +1,5 @@ #include "definition.hpp" +#include #include "error.hpp" #include "ast.hpp" #include "instruction.hpp" @@ -62,7 +63,10 @@ void definition_data::insert_constructors() const { type_app* return_app = new type_app(std::move(this_type_ptr)); type_ptr return_type(return_app); for(auto& var : vars) { - if(var_set.find(var) != var_set.end()) throw 0; + if(var_set.find(var) != var_set.end()) + throw std::runtime_error( + std::string("type variable ") + + var + std::string(" used twice in data type definition.")); var_set.insert(var); return_app->arguments.push_back(type_ptr(new type_var(var))); } @@ -121,8 +125,7 @@ void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) { dependency_graph.add_function(def_defn.second->name); for(auto& dependency : def_defn.second->nearby_variables) { - if(defs_defn.find(dependency) == defs_defn.end()) - throw 0; + assert(defs_defn.find(dependency) != defs_defn.end()); dependency_graph.add_edge(def_defn.second->name, dependency); } } diff --git a/code/compiler/13/env.cpp b/code/compiler/13/env.cpp index 818cf5d..74b1650 100644 --- a/code/compiler/13/env.cpp +++ b/code/compiler/13/env.cpp @@ -1,9 +1,10 @@ #include "env.hpp" +#include int env_var::get_offset(const std::string& name) const { if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; + assert(parent); + return parent->get_offset(name) + 1; } bool env_var::has_variable(const std::string& name) const { @@ -13,8 +14,8 @@ bool env_var::has_variable(const std::string& name) const { } int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; + assert(parent); + return parent->get_offset(name) + offset; } bool env_offset::has_variable(const std::string& name) const { diff --git a/code/compiler/13/main.cpp b/code/compiler/13/main.cpp index 6f844ca..ec21e2b 100644 --- a/code/compiler/13/main.cpp +++ b/code/compiler/13/main.cpp @@ -103,12 +103,12 @@ void output_llvm(llvm_context& ctx, const std::string& filename) { std::error_code ec; llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None); if (ec) { - throw 0; + throw std::runtime_error("failed to open object file for writing"); } else { llvm::CodeGenFileType type = llvm::CGFT_ObjectFile; llvm::legacy::PassManager pm; if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { - throw 0; + throw std::runtime_error("failed to add passes to pass manager"); } else { pm.run(ctx.module); file.close(); @@ -132,10 +132,13 @@ void gen_llvm(global_scope& scope) { int main(int argc, char** argv) { if(argc != 2) { - std::cout << "please enter a file to compile." << std::endl; + std::cerr << "please enter a file to compile." << std::endl; } parse_driver driver(argv[1]); - driver.run_parse(); + if(!driver.run_parse()) { + std::cerr << "failed to open file " << argv[1] << std::endl; + exit(1); + } type_mgr mgr; type_env_ptr env(new type_env); @@ -154,8 +157,10 @@ int main(int argc, char** argv) { scope.compile(); gen_llvm(scope); } catch(unification_error& err) { - err.pretty_print(std::cout, driver, mgr); + err.pretty_print(std::cerr, driver, mgr); } catch(type_error& err) { - err.pretty_print(std::cout, driver); + err.pretty_print(std::cerr, driver); + } catch(std::runtime_error& err) { + std::cerr << err.what() << std::endl; } } diff --git a/code/compiler/13/parse_driver.hpp b/code/compiler/13/parse_driver.hpp index 9fd1f97..a12b41b 100644 --- a/code/compiler/13/parse_driver.hpp +++ b/code/compiler/13/parse_driver.hpp @@ -26,9 +26,9 @@ struct parse_driver { parse_driver(const std::string& file) : file_name(file), file_offset(0) {} - void run_parse() { + bool run_parse() { file_stream.open(file_name); - if(!file_stream.good()) throw 0; + if(!file_stream.good()) return false; line_offsets.push_back(0); yyscan_t scanner; scanner_init(this, &scanner); @@ -36,6 +36,7 @@ struct parse_driver { parser(); scanner_destroy(&scanner); read_file = string_stream.str(); + return true; } int get() { diff --git a/code/compiler/13/parsed_type.cpp b/code/compiler/13/parsed_type.cpp index c69e50a..cd73792 100644 --- a/code/compiler/13/parsed_type.cpp +++ b/code/compiler/13/parsed_type.cpp @@ -1,15 +1,26 @@ #include "parsed_type.hpp" +#include #include "type.hpp" #include "type_env.hpp" +#include "error.hpp" type_ptr parsed_type_app::to_type( const std::set& vars, const type_env& e) const { auto parent_type = e.lookup_type(name); - if(parent_type == nullptr) throw 0; + if(parent_type == nullptr) + throw type_error(std::string("no such type or type constructor ") + name); type_base* base_type; - if(!(base_type = dynamic_cast(parent_type.get()))) throw 0; - if(base_type->arity != arguments.size()) throw 0; + if(!(base_type = dynamic_cast(parent_type.get()))) + throw type_error(std::string("invalid type ") + name); + if(base_type->arity != arguments.size()) { + std::ostringstream error_stream; + error_stream << "invalid application of type "; + error_stream << name; + error_stream << "(" << base_type->arity << " arguments expected, "; + error_stream << "but " << arguments.size() << " were provided)"; + throw type_error(error_stream.str()); + } type_app* new_app = new type_app(std::move(parent_type)); type_ptr to_return(new_app); @@ -22,7 +33,8 @@ type_ptr parsed_type_app::to_type( type_ptr parsed_type_var::to_type( const std::set& vars, const type_env& e) const { - if(vars.find(var) == vars.end()) throw 0; + if(vars.find(var) == vars.end()) + throw type_error(std::string("the type variable ") + var + std::string(" was not explicitly declared.")); return type_ptr(new type_var(var)); } diff --git a/code/compiler/13/type_env.cpp b/code/compiler/13/type_env.cpp index f42e46a..4c5d3ad 100644 --- a/code/compiler/13/type_env.cpp +++ b/code/compiler/13/type_env.cpp @@ -1,5 +1,6 @@ #include "type_env.hpp" #include "type.hpp" +#include "error.hpp" void type_env::find_free(const type_mgr& mgr, std::set& into) const { if(parent != nullptr) parent->find_free(mgr, into); @@ -61,14 +62,15 @@ void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) { } void type_env::bind_type(const std::string& type_name, type_ptr t) { - if(lookup_type(type_name) != nullptr) throw 0; + if(lookup_type(type_name) != nullptr) + throw type_error("redefinition of type"); type_names[type_name] = t; } void type_env::generalize(const std::string& name, const group& grp, type_mgr& mgr) { auto names_it = names.find(name); - if(names_it == names.end()) throw 0; - if(names_it->second.type->forall.size() > 0) throw 0; + assert(names_it != names.end()); + assert(names_it->second.type->forall.size() == 0); std::set free_in_type; std::set free_in_env;