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) {
|
std::vector<instruction_ptr>& make_case_for(tag_type tag) {
|
||||||
if(default_case)
|
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];
|
return defined_cases[tag];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<instruction_ptr>& make_default_case() {
|
std::vector<instruction_ptr>& make_default_case() {
|
||||||
if(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>());
|
default_case.emplace(std::vector<instruction_ptr>());
|
||||||
return *default_case;
|
return *default_case;
|
||||||
}
|
}
|
||||||
@ -285,7 +285,7 @@ struct case_strategy_bool {
|
|||||||
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())) ||
|
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())) ||
|
||||||
(cpat->constr != "True" && cpat->constr != "False") ||
|
(cpat->constr != "True" && cpat->constr != "False") ||
|
||||||
cpat->params.size() != 0)
|
cpat->params.size() != 0)
|
||||||
throw type_error(
|
throw compiler_error(
|
||||||
"pattern cannot be converted to a boolean",
|
"pattern cannot be converted to a boolean",
|
||||||
pt->loc);
|
pt->loc);
|
||||||
return cpat->constr == "True";
|
return cpat->constr == "True";
|
||||||
@ -335,7 +335,7 @@ struct case_strategy_data {
|
|||||||
repr_type repr_from_pattern(const pattern_ptr& pt) {
|
repr_type repr_from_pattern(const pattern_ptr& pt) {
|
||||||
pattern_constr* cpat;
|
pattern_constr* cpat;
|
||||||
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())))
|
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())))
|
||||||
throw type_error(
|
throw compiler_error(
|
||||||
"pattern cannot be interpreted as constructor.",
|
"pattern cannot be interpreted as constructor.",
|
||||||
pt->loc);
|
pt->loc);
|
||||||
return std::make_pair(
|
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;
|
pattern_var* vpat;
|
||||||
if((vpat = dynamic_cast<pattern_var*>(branch->pat.get()))) {
|
if((vpat = dynamic_cast<pattern_var*>(branch->pat.get()))) {
|
||||||
if(cases.defined_cases_count() == strategy.case_count())
|
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();
|
auto& branch_into = cases.make_default_case();
|
||||||
env_ptr new_env(new env_var(vpat->var, env));
|
env_ptr new_env(new env_var(vpat->var, env));
|
||||||
branch->expr->compile(new_env, branch_into);
|
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() ||
|
if(!(cases.defined_cases_count() == strategy.case_count() ||
|
||||||
cases.default_case_defined()))
|
cases.default_case_defined()))
|
||||||
throw type_error("incomplete patterns", node.loc);
|
throw compiler_error("incomplete patterns", node.loc);
|
||||||
|
|
||||||
strategy.into_instructions(cases, into);
|
strategy.into_instructions(cases, into);
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ void definition_data::insert_constructors() const {
|
|||||||
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())
|
if(var_set.find(var) != var_set.end())
|
||||||
throw std::runtime_error(
|
throw compiler_error(
|
||||||
std::string("type variable ") +
|
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);
|
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)));
|
||||||
}
|
}
|
||||||
|
31
13/error.cpp
31
13/error.cpp
@ -1,19 +1,32 @@
|
|||||||
#include "error.hpp"
|
#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 {
|
const char* type_error::what() const noexcept {
|
||||||
return "an error occured while checking the types of the program";
|
return "an error occured while checking the types of the program";
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_error::pretty_print(std::ostream& to, parse_driver& drv) {
|
void type_error::pretty_print(std::ostream& to, parse_driver& drv) {
|
||||||
to << "encountered error while typechecking program: ";
|
print_about(to);
|
||||||
to << description << std::endl;
|
print_location(to, drv, true);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unification_error::pretty_print(std::ostream& to, parse_driver& drv, type_mgr& mgr) {
|
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>;
|
using maybe_location = std::optional<yy::location>;
|
||||||
|
|
||||||
struct type_error : std::exception {
|
struct compiler_error : std::exception {
|
||||||
std::string description;
|
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;
|
std::optional<yy::location> loc;
|
||||||
|
|
||||||
type_error(std::string d, maybe_location l = std::nullopt)
|
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;
|
const char* what() const noexcept override;
|
||||||
void pretty_print(std::ostream& to, parse_driver& drv);
|
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"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
void yy::parser::error(const yy::location& loc, const std::string& msg) {
|
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) {
|
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;
|
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 std::runtime_error("failed to open object file for writing");
|
throw compiler_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 std::runtime_error("failed to add passes to pass manager");
|
throw compiler_error("failed to add passes to pass manager");
|
||||||
} else {
|
} else {
|
||||||
pm.run(ctx.module);
|
pm.run(ctx.module);
|
||||||
file.close();
|
file.close();
|
||||||
@ -177,10 +177,11 @@ 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::cerr << "please enter a file to compile." << std::endl;
|
std::cerr << "please enter a file to compile." << std::endl;
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
parse_driver driver(argv[1]);
|
parse_driver driver(argv[1]);
|
||||||
if(!driver.run_parse()) {
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ int main(int argc, char** argv) {
|
|||||||
err.pretty_print(std::cerr, driver, mgr);
|
err.pretty_print(std::cerr, driver, mgr);
|
||||||
} catch(type_error& err) {
|
} catch(type_error& err) {
|
||||||
err.pretty_print(std::cerr, driver);
|
err.pretty_print(std::cerr, driver);
|
||||||
} catch(std::runtime_error& err) {
|
} catch (compiler_error& err) {
|
||||||
std::cerr << err.what() << std::endl;
|
err.pretty_print(std::cerr, driver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
bool parse_driver::run_parse() {
|
bool parse_driver::run_parse() {
|
||||||
FILE* stream = fopen(file_name.c_str(), "r");
|
FILE* stream = fopen(file_name.c_str(), "r");
|
||||||
if(!stream) return false;
|
if(!stream) return false;
|
||||||
string_stream = std::ostringstream();
|
|
||||||
file_offset = 0;
|
|
||||||
line_offsets.push_back(0);
|
line_offsets.push_back(0);
|
||||||
yyscan_t scanner;
|
yyscan_t scanner;
|
||||||
yylex_init(&scanner);
|
yylex_init(&scanner);
|
||||||
@ -29,27 +27,27 @@ void parse_driver::mark_line() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t parse_driver::get_index(int line, int column) {
|
size_t parse_driver::get_index(int line, int column) {
|
||||||
assert(line > 0);
|
assert(line > 0 && line <= line_offsets.size());
|
||||||
assert(line <= line_offsets.size());
|
return line_offsets[line-1] + column - 1;
|
||||||
size_t file_offset = line_offsets[line-1];
|
|
||||||
file_offset += column - 1;
|
|
||||||
return file_offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t parse_driver::get_line_end(int line) {
|
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);
|
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 print_start = get_index(loc.begin.line, 1);
|
||||||
size_t highlight_start = get_index(loc.begin.line, loc.begin.column);
|
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 highlight_end = get_index(loc.end.line, loc.end.column);
|
||||||
size_t print_end = get_line_end(loc.end.line);
|
size_t print_end = get_line_end(loc.end.line);
|
||||||
const char* content = file_contents.c_str();
|
const char* content = file_contents.c_str();
|
||||||
stream.write(content + print_start, highlight_start - print_start);
|
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.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);
|
stream.write(content + highlight_end, print_end - highlight_end);
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,13 @@ void scanner_destroy(yyscan_t* scanner);
|
|||||||
struct parse_driver {
|
struct parse_driver {
|
||||||
std::string file_name;
|
std::string file_name;
|
||||||
std::ostringstream string_stream;
|
std::ostringstream string_stream;
|
||||||
|
std::string file_contents;
|
||||||
|
|
||||||
yy::location location;
|
yy::location location;
|
||||||
size_t file_offset;
|
size_t file_offset;
|
||||||
|
|
||||||
std::vector<size_t> line_offsets;
|
std::vector<size_t> line_offsets;
|
||||||
|
|
||||||
definition_group global_defs;
|
definition_group global_defs;
|
||||||
std::string file_contents;
|
|
||||||
|
|
||||||
parse_driver(const std::string& file)
|
parse_driver(const std::string& file)
|
||||||
: file_name(file), file_offset(0) {}
|
: file_name(file), file_offset(0) {}
|
||||||
@ -30,7 +30,10 @@ struct parse_driver {
|
|||||||
void mark_line();
|
void mark_line();
|
||||||
size_t get_index(int line, int column);
|
size_t get_index(int line, int column);
|
||||||
size_t get_line_end(int line);
|
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)
|
#define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv)
|
||||||
|
Loading…
Reference in New Issue
Block a user