Refactor errors and update post draft.

This commit is contained in:
Danila Fedorin 2020-09-11 21:29:49 -07:00
parent 4cdb9360fb
commit 03465c07ce
7 changed files with 68 additions and 39 deletions

View File

@ -235,13 +235,13 @@ struct case_mappings {
std::vector<instruction_ptr>& make_case_for(tag_type tag) {
if(default_case)
throw type_error("attempted pattern match after catch-all");
throw compiler_error("attempted pattern match after catch-all");
return defined_cases[tag];
}
std::vector<instruction_ptr>& make_default_case() {
if(default_case)
throw type_error("attempted repeated use of catch-all");
throw compiler_error("attempted repeated use of catch-all");
default_case.emplace(std::vector<instruction_ptr>());
return *default_case;
}
@ -285,7 +285,7 @@ struct case_strategy_bool {
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())) ||
(cpat->constr != "True" && cpat->constr != "False") ||
cpat->params.size() != 0)
throw type_error(
throw compiler_error(
"pattern cannot be converted to a boolean",
pt->loc);
return cpat->constr == "True";
@ -335,7 +335,7 @@ struct case_strategy_data {
repr_type repr_from_pattern(const pattern_ptr& pt) {
pattern_constr* cpat;
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())))
throw type_error(
throw compiler_error(
"pattern cannot be interpreted as constructor.",
pt->loc);
return std::make_pair(
@ -398,7 +398,7 @@ void compile_case(const ast_case& node, const env_ptr& env, const type* type, st
pattern_var* vpat;
if((vpat = dynamic_cast<pattern_var*>(branch->pat.get()))) {
if(cases.defined_cases_count() == strategy.case_count())
throw type_error("redundant catch-all pattern", branch->pat->loc);
throw compiler_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);
@ -412,7 +412,7 @@ void compile_case(const ast_case& node, const env_ptr& env, const type* type, st
if(!(cases.defined_cases_count() == strategy.case_count() ||
cases.default_case_defined()))
throw type_error("incomplete patterns", node.loc);
throw compiler_error("incomplete patterns", node.loc);
strategy.into_instructions(cases, into);
}

View File

@ -64,9 +64,9 @@ void definition_data::insert_constructors() const {
type_ptr return_type(return_app);
for(auto& var : vars) {
if(var_set.find(var) != var_set.end())
throw std::runtime_error(
throw compiler_error(
std::string("type variable ") +
var + std::string(" used twice in data type definition."));
var + std::string(" used twice in data type definition."), loc);
var_set.insert(var);
return_app->arguments.push_back(type_ptr(new type_var(var)));
}

View File

@ -1,19 +1,32 @@
#include "error.hpp"
const char* compiler_error::what() const noexcept {
return "an error occured while compiling the program";
}
void compiler_error::print_about(std::ostream& to) {
to << what() << ": ";
to << description << std::endl;
}
void compiler_error::print_location(std::ostream& to, parse_driver& drv, bool highlight) {
if(!loc) return;
to << "occuring on line " << loc->begin.line << ":" << std::endl;
drv.print_location(to, *loc, highlight);
}
void compiler_error::pretty_print(std::ostream& to, parse_driver& drv) {
print_about(to);
print_location(to, drv);
}
const char* type_error::what() const noexcept {
return "an error occured while checking the types of the program";
}
void type_error::pretty_print(std::ostream& to, parse_driver& drv) {
to << "encountered error while typechecking program: ";
to << description << std::endl;
if(loc) {
to << "occuring on line " << loc->begin.line << ":" << std::endl;
to << std::endl << "```" << std::endl;
drv.print_highlighted_location(to, *loc);
to << "```" << std::endl << std::endl;
}
print_about(to);
print_location(to, drv, true);
}
void unification_error::pretty_print(std::ostream& to, parse_driver& drv, type_mgr& mgr) {

View File

@ -7,12 +7,26 @@
using maybe_location = std::optional<yy::location>;
struct type_error : std::exception {
struct compiler_error : std::exception {
std::string description;
maybe_location loc;
compiler_error(std::string d, maybe_location l = std::nullopt)
: description(std::move(d)), loc(std::move(l)) {}
const char* what() const noexcept override;
void print_about(std::ostream& to);
void print_location(std::ostream& to, parse_driver& drv, bool highlight = false);
void pretty_print(std::ostream& to, parse_driver& drv);
};
struct type_error : compiler_error {
std::optional<yy::location> loc;
type_error(std::string d, maybe_location l = std::nullopt)
: description(std::move(d)), loc(std::move(l)) {}
: compiler_error(std::move(d), std::move(l)) {}
const char* what() const noexcept override;
void pretty_print(std::ostream& to, parse_driver& drv);

View File

@ -20,7 +20,7 @@
#include "llvm/Target/TargetMachine.h"
void yy::parser::error(const yy::location& loc, const std::string& msg) {
std::cout << "An error occured: " << msg << std::endl;
std::cerr << "An error occured: " << msg << std::endl;
}
void prelude_types(definition_group& defs, type_env_ptr env) {
@ -110,12 +110,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 std::runtime_error("failed to open object file for writing");
throw compiler_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 std::runtime_error("failed to add passes to pass manager");
throw compiler_error("failed to add passes to pass manager");
} else {
pm.run(ctx.module);
file.close();
@ -177,10 +177,11 @@ void gen_llvm(global_scope& scope) {
int main(int argc, char** argv) {
if(argc != 2) {
std::cerr << "please enter a file to compile." << std::endl;
exit(1);
}
parse_driver driver(argv[1]);
if(!driver.run_parse()) {
std::cerr << "failed to open file " << argv[1] << std::endl;
std::cerr << "failed to parse file " << argv[1] << std::endl;
exit(1);
}
@ -207,7 +208,7 @@ int main(int argc, char** argv) {
err.pretty_print(std::cerr, driver, mgr);
} catch(type_error& err) {
err.pretty_print(std::cerr, driver);
} catch(std::runtime_error& err) {
std::cerr << err.what() << std::endl;
} catch (compiler_error& err) {
err.pretty_print(std::cerr, driver);
}
}

View File

@ -5,8 +5,6 @@
bool parse_driver::run_parse() {
FILE* stream = fopen(file_name.c_str(), "r");
if(!stream) return false;
string_stream = std::ostringstream();
file_offset = 0;
line_offsets.push_back(0);
yyscan_t scanner;
yylex_init(&scanner);
@ -29,27 +27,27 @@ void parse_driver::mark_line() {
}
size_t parse_driver::get_index(int line, int column) {
assert(line > 0);
assert(line <= line_offsets.size());
size_t file_offset = line_offsets[line-1];
file_offset += column - 1;
return file_offset;
assert(line > 0 && line <= line_offsets.size());
return line_offsets[line-1] + column - 1;
}
size_t parse_driver::get_line_end(int line) {
if(line > line_offsets.size()) return file_contents.size();
if(line == line_offsets.size()) return file_contents.size();
return get_index(line+1, 1);
}
void parse_driver::print_highlighted_location(std::ostream& stream, const yy::location& loc) {
void parse_driver::print_location(
std::ostream& stream,
const yy::location& loc,
bool highlight) {
size_t print_start = get_index(loc.begin.line, 1);
size_t highlight_start = get_index(loc.begin.line, loc.begin.column);
size_t highlight_end = get_index(loc.end.line, loc.end.column);
size_t print_end = get_line_end(loc.end.line);
const char* content = file_contents.c_str();
stream.write(content + print_start, highlight_start - print_start);
stream << "\033[4;31m";
if(highlight) stream << "\033[4;31m";
stream.write(content + highlight_start, highlight_end - highlight_start);
stream << "\033[0m";
if(highlight) stream << "\033[0m";
stream.write(content + highlight_end, print_end - highlight_end);
}

View File

@ -14,13 +14,13 @@ void scanner_destroy(yyscan_t* scanner);
struct parse_driver {
std::string file_name;
std::ostringstream string_stream;
std::string file_contents;
yy::location location;
size_t file_offset;
std::vector<size_t> line_offsets;
definition_group global_defs;
std::string file_contents;
parse_driver(const std::string& file)
: file_name(file), file_offset(0) {}
@ -30,7 +30,10 @@ struct parse_driver {
void mark_line();
size_t get_index(int line, int column);
size_t get_line_end(int line);
void print_highlighted_location(std::ostream& stream, const yy::location& loc);
void print_location(
std::ostream& stream,
const yy::location& loc,
bool highlight = true);
};
#define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv)