Refactor errors and update post draft.
This commit is contained in:
parent
4cdb9360fb
commit
03465c07ce
12
13/ast.cpp
12
13/ast.cpp
@ -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);
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
|
31
13/error.cpp
31
13/error.cpp
@ -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) {
|
||||
|
18
13/error.hpp
18
13/error.hpp
@ -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);
|
||||
|
13
13/main.cpp
13
13/main.cpp
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user