Replace throw 0 with real exceptions or assertions.

This commit is contained in:
Danila Fedorin 2020-09-09 17:19:23 -07:00
parent e337992410
commit 9769b3e396
6 changed files with 46 additions and 22 deletions

View File

@ -1,4 +1,5 @@
#include "definition.hpp" #include "definition.hpp"
#include <cassert>
#include "error.hpp" #include "error.hpp"
#include "ast.hpp" #include "ast.hpp"
#include "instruction.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_app* return_app = new type_app(std::move(this_type_ptr));
type_ptr return_type(return_app); type_ptr return_type(return_app);
for(auto& var : vars) { 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); var_set.insert(var);
return_app->arguments.push_back(type_ptr(new type_var(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); dependency_graph.add_function(def_defn.second->name);
for(auto& dependency : def_defn.second->nearby_variables) { for(auto& dependency : def_defn.second->nearby_variables) {
if(defs_defn.find(dependency) == defs_defn.end()) assert(defs_defn.find(dependency) != defs_defn.end());
throw 0;
dependency_graph.add_edge(def_defn.second->name, dependency); dependency_graph.add_edge(def_defn.second->name, dependency);
} }
} }

View File

@ -1,9 +1,10 @@
#include "env.hpp" #include "env.hpp"
#include <cassert>
int env_var::get_offset(const std::string& name) const { int env_var::get_offset(const std::string& name) const {
if(name == this->name) return 0; if(name == this->name) return 0;
if(parent) return parent->get_offset(name) + 1; assert(parent);
throw 0; return parent->get_offset(name) + 1;
} }
bool env_var::has_variable(const std::string& name) const { 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 { int env_offset::get_offset(const std::string& name) const {
if(parent) return parent->get_offset(name) + offset; assert(parent);
throw 0; return parent->get_offset(name) + offset;
} }
bool env_offset::has_variable(const std::string& name) const { bool env_offset::has_variable(const std::string& name) const {

View File

@ -103,12 +103,12 @@ void output_llvm(llvm_context& ctx, const std::string& filename) {
std::error_code ec; std::error_code ec;
llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None); llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None);
if (ec) { if (ec) {
throw 0; throw std::runtime_error("failed to open object file for writing");
} else { } else {
llvm::CodeGenFileType type = llvm::CGFT_ObjectFile; llvm::CodeGenFileType type = llvm::CGFT_ObjectFile;
llvm::legacy::PassManager pm; llvm::legacy::PassManager pm;
if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) {
throw 0; throw std::runtime_error("failed to add passes to pass manager");
} else { } else {
pm.run(ctx.module); pm.run(ctx.module);
file.close(); file.close();
@ -132,10 +132,13 @@ void gen_llvm(global_scope& scope) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
if(argc != 2) { 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]); 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_mgr mgr;
type_env_ptr env(new type_env); type_env_ptr env(new type_env);
@ -154,8 +157,10 @@ int main(int argc, char** argv) {
scope.compile(); scope.compile();
gen_llvm(scope); gen_llvm(scope);
} catch(unification_error& err) { } catch(unification_error& err) {
err.pretty_print(std::cout, driver, mgr); err.pretty_print(std::cerr, driver, mgr);
} catch(type_error& err) { } 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;
} }
} }

View File

@ -26,9 +26,9 @@ struct parse_driver {
parse_driver(const std::string& file) parse_driver(const std::string& file)
: file_name(file), file_offset(0) {} : file_name(file), file_offset(0) {}
void run_parse() { bool run_parse() {
file_stream.open(file_name); file_stream.open(file_name);
if(!file_stream.good()) throw 0; if(!file_stream.good()) return false;
line_offsets.push_back(0); line_offsets.push_back(0);
yyscan_t scanner; yyscan_t scanner;
scanner_init(this, &scanner); scanner_init(this, &scanner);
@ -36,6 +36,7 @@ struct parse_driver {
parser(); parser();
scanner_destroy(&scanner); scanner_destroy(&scanner);
read_file = string_stream.str(); read_file = string_stream.str();
return true;
} }
int get() { int get() {

View File

@ -1,15 +1,26 @@
#include "parsed_type.hpp" #include "parsed_type.hpp"
#include <sstream>
#include "type.hpp" #include "type.hpp"
#include "type_env.hpp" #include "type_env.hpp"
#include "error.hpp"
type_ptr parsed_type_app::to_type( type_ptr parsed_type_app::to_type(
const std::set<std::string>& vars, const std::set<std::string>& vars,
const type_env& e) const { const type_env& e) const {
auto parent_type = e.lookup_type(name); 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; type_base* base_type;
if(!(base_type = dynamic_cast<type_base*>(parent_type.get()))) throw 0; if(!(base_type = dynamic_cast<type_base*>(parent_type.get())))
if(base_type->arity != arguments.size()) throw 0; 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_app* new_app = new type_app(std::move(parent_type));
type_ptr to_return(new_app); type_ptr to_return(new_app);
@ -22,7 +33,8 @@ type_ptr parsed_type_app::to_type(
type_ptr parsed_type_var::to_type( type_ptr parsed_type_var::to_type(
const std::set<std::string>& vars, const std::set<std::string>& vars,
const type_env& e) const { 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)); return type_ptr(new type_var(var));
} }

View File

@ -1,5 +1,6 @@
#include "type_env.hpp" #include "type_env.hpp"
#include "type.hpp" #include "type.hpp"
#include "error.hpp"
void type_env::find_free(const type_mgr& mgr, std::set<std::string>& into) const { void type_env::find_free(const type_mgr& mgr, std::set<std::string>& into) const {
if(parent != nullptr) parent->find_free(mgr, into); 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) { 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; type_names[type_name] = t;
} }
void type_env::generalize(const std::string& name, const group& grp, type_mgr& mgr) { void type_env::generalize(const std::string& name, const group& grp, type_mgr& mgr) {
auto names_it = names.find(name); auto names_it = names.find(name);
if(names_it == names.end()) throw 0; assert(names_it != names.end());
if(names_it->second.type->forall.size() > 0) throw 0; assert(names_it->second.type->forall.size() == 0);
std::set<std::string> free_in_type; std::set<std::string> free_in_type;
std::set<std::string> free_in_env; std::set<std::string> free_in_env;