Skip to content

Commit

Permalink
Add beautiful error messages.
Browse files Browse the repository at this point in the history
This is easy now that we have proper location encoding.

Example:

    test.sp(3) : error 017: undefined symbol "ham"
         3 |     int hello = ham;
    -------------------------^

    test.sp(4) : error 017: undefined symbol "hhello"
         4 |     return hhello
    --------------------^
  • Loading branch information
dvander committed Sep 30, 2023
1 parent 225827e commit 8c76cd9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 8 deletions.
31 changes: 26 additions & 5 deletions compiler/errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ MessageBuilder::~MessageBuilder()
auto& cc = CompileContext::get();

ErrorReport report;
report.loc = where_;
report.number = number_;
if (where_.valid())
report.fileno = cc.sources()->GetSourceFileIndex(where_);
Expand All @@ -180,8 +181,12 @@ MessageBuilder::~MessageBuilder()
else
report.file = cc.sources()->opened_files().at(0);

uint32_t actual_line = cc.sources()->GetLineAndCol(where_, &report.col);

// Rely on tokline when it's there, but... we should ditch it here, we
// have the technology.
if (where_.valid() && !where_.line)
where_.line = cc.sources()->GetLineAndCol(where_, &report.col);
where_.line = actual_line;
report.lineno = std::max(where_.line, 1);

report.type = DeduceErrorType(number_);
Expand Down Expand Up @@ -264,9 +269,20 @@ ReportManager::ReportError(ErrorReport&& report)
cc_.set_must_abort();
}

void
ReportManager::DumpErrorReport(bool clear)
{
void DumpDiagnostic(FILE* fp, const ErrorReport& report) {
auto line = report.file->GetLine(report.lineno);
while (!line.empty() && (line.back() == '\r' || line.back() == '\n'))
line.pop_back();

fprintf(fp, "%6u | %s\n", report.lineno, line.c_str());

uint32_t num_dashes = 9 + report.col - 1;
for (uint32_t i = 0; i < num_dashes; i++)
fprintf(fp, "-");
fprintf(fp, "^\n");
}

void ReportManager::DumpErrorReport(bool clear) {
FILE* stdfp = cc_.options()->use_stderr ? stderr : stdout;

FILE* fp = nullptr;
Expand All @@ -282,8 +298,13 @@ ReportManager::DumpErrorReport(bool clear)
return a.fileno > b.fileno;
});

for (const auto& report : error_list_)
for (const auto& report : error_list_) {
fprintf(fp, "%s", report.message.c_str());
if (report.loc.valid())
DumpDiagnostic(fp, report);
if (&report != &error_list_.back())
fprintf(fp, "\n");
}
fflush(fp);

if (fp != stdfp)
Expand Down
38 changes: 35 additions & 3 deletions compiler/source-file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ void SourceFile::ComputeLineExtents() {
if (!line_extents_.empty())
return;

line_extents_.emplace_back(0);
tr::vector<uint32_t> extents;
extents.emplace_back(0);
for (uint32_t i = 0; i < data_.size(); i++) {
if (data_[i] != '\r' && data_[i] != '\n')
continue;
Expand All @@ -126,10 +127,13 @@ void SourceFile::ComputeLineExtents() {
if (i + 1 < data_.size() && data_[i + 1] == '\n')
i++;
}
line_extents_.emplace_back(i + 1);
extents.emplace_back(i + 1);
}

line_extents_.shrink_to_fit();

line_extents_.resize(extents.size());
for (size_t i = 0; i < extents.size(); i++)
line_extents_[i] = extents[i];
}

bool SourceFile::OffsetToLineAndCol(uint32_t offset, uint32_t* line, uint32_t* col) {
Expand Down Expand Up @@ -178,4 +182,32 @@ bool SourceFile::OffsetToLineAndCol(uint32_t offset, uint32_t* line, uint32_t* c
return false;
}

bool SourceFile::OffsetOfLine(uint32_t line, uint32_t* offset) {
ComputeLineExtents();

uint32_t line_index = line - 1;
if (line_index > line_extents_.size())
return false;

if (line_index == line_extents_.size())
*offset = data_.size();
else
*offset = line_extents_[line_index];
return true;
}

tr::string SourceFile::GetLine(uint32_t line) {
ComputeLineExtents();

uint32_t offset;
if (!OffsetOfLine(line, &offset))
return {};

uint32_t end;
if (!OffsetOfLine(line + 1, &end))
end = data_.size();

return data_.substr(offset, end - offset);
}

} // namespace sp
2 changes: 2 additions & 0 deletions compiler/source-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class SourceFile : public std::enable_shared_from_this<SourceFile>
std::shared_ptr<SourceFile> to_shared() { return shared_from_this(); }

bool OffsetToLineAndCol(uint32_t offset, uint32_t* line, uint32_t* col = nullptr);
bool OffsetOfLine(uint32_t line, uint32_t* offset);
tr::string GetLine(uint32_t line);

private:
bool Open(const std::string& file_name);
Expand Down

0 comments on commit 8c76cd9

Please sign in to comment.