Skip to content

Commit f3187ba

Browse files
XX Create new structure FileLocations to handle imported file errors
1 parent ce4612d commit f3187ba

File tree

11 files changed

+175
-136
lines changed

11 files changed

+175
-136
lines changed

src/bin/lpython.cpp

Lines changed: 50 additions & 48 deletions
Large diffs are not rendered by default.

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
380380
void debug_get_line_column(const uint32_t &loc_first,
381381
uint32_t &line, uint32_t &column) {
382382
LocationManager lm;
383-
lm.in_filename = infile;
383+
LocationManager::FileLocations fl;
384+
fl.in_filename = infile;
385+
lm.files.push_back(fl);
384386
lm.init_simple(LFortran::read_file(infile));
385387
lm.pos_to_linecol(lm.output_to_input_pos(loc_first, false), line, column);
386388
}

src/libasr/diagnostics.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,16 @@ bool Diagnostics::has_error() const {
6161
return false;
6262
}
6363

64-
std::string Diagnostics::render(const std::string &input,
65-
const LocationManager &lm, const CompilerOptions &compiler_options) {
64+
std::string Diagnostics::render(const std::string &input1,
65+
LocationManager &lm, const CompilerOptions &compiler_options) {
6666
std::string out;
67+
std::string input;
6768
for (auto &d : this->diagnostics) {
6869
if (compiler_options.no_warnings && d.level != Level::Error) {
6970
continue;
7071
}
72+
read_file(lm.files.back().in_filename, input);
73+
lm.init_simple(input);
7174
if (compiler_options.error_format == "human") {
7275
out += render_diagnostic_human(d, input, lm,
7376
compiler_options.use_colors,
@@ -78,6 +81,7 @@ std::string Diagnostics::render(const std::string &input,
7881
} else {
7982
throw LCompilersException("Error format not supported.");
8083
}
84+
lm.files.pop_back();
8185
}
8286
if (compiler_options.error_format == "human") {
8387
if (this->diagnostics.size() > 0 && !compiler_options.no_error_banner) {
@@ -114,7 +118,7 @@ void populate_span(diag::Span &s, const LocationManager &lm,
114118
s.first_line, s.first_column);
115119
lm.pos_to_linecol(lm.output_to_input_pos(s.loc.last, true),
116120
s.last_line, s.last_column);
117-
s.filename = lm.in_filename;
121+
s.filename = lm.files.back().in_filename;
118122
for (uint32_t i = s.first_line; i <= s.last_line; i++) {
119123
s.source_code.push_back(get_line(input, i));
120124
}
@@ -178,7 +182,7 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) {
178182
std::string type_color = "";
179183
switch (d.level) {
180184
case (Level::Error):
181-
primary_color = red_bold;
185+
primary_color = red_bold;
182186
type_color = primary_color;
183187
switch (d.stage) {
184188
case (Stage::CPreprocessor):
@@ -205,17 +209,17 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) {
205209
}
206210
break;
207211
case (Level::Warning):
208-
primary_color = yellow_bold;
212+
primary_color = yellow_bold;
209213
type_color = primary_color;
210214
message_type = "warning";
211215
break;
212216
case (Level::Note):
213-
primary_color = bold;
217+
primary_color = bold;
214218
type_color = primary_color;
215219
message_type = "note";
216220
break;
217221
case (Level::Help):
218-
primary_color = bold;
222+
primary_color = bold;
219223
type_color = primary_color;
220224
message_type = "help";
221225
break;

src/libasr/diagnostics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ struct Diagnostics {
114114
std::vector<Diagnostic> diagnostics;
115115

116116
std::string render(const std::string &input,
117-
const LocationManager &lm, const CompilerOptions &compiler_options);
117+
LocationManager &lm, const CompilerOptions &compiler_options);
118118

119119
// Returns true iff diagnostics contains at least one error message
120120
bool has_error() const;

src/libasr/location.h

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -94,50 +94,62 @@ struct LocationManager {
9494
//
9595
//
9696
//
97-
std::vector<uint32_t> out_start; // consecutive intervals in the output code
98-
std::vector<uint32_t> in_start; // start + size in the original code
99-
std::vector<uint32_t> in_newlines; // position of all \n in the original code
97+
struct FileLocations {
98+
std::vector<uint32_t> out_start; // consecutive intervals in the output code
99+
std::vector<uint32_t> in_start; // start + size in the original code
100+
std::vector<uint32_t> in_newlines; // position of all \n in the original code
100101

101-
// For preprocessor (if preprocessor==true).
102-
// TODO: design a common structure, that also works with #include, that
103-
// has these mappings for each file
104-
bool preprocessor = false;
105-
std::string in_filename;
106-
uint32_t current_line=0;
107-
std::vector<uint32_t> out_start0; // consecutive intervals in the output code
108-
std::vector<uint32_t> in_start0; // start + size in the original code
109-
std::vector<uint32_t> in_size0; // Size of the `in` interval
110-
std::vector<uint32_t> interval_type0; // 0 .... 1:1; 1 ... many to many;
111-
std::vector<uint32_t> in_newlines0; // position of all \n in the original code
112-
// std::vector<uint32_t> filename_id; // file name for each interval, ID
113-
// std::vector<std::string> filenames; // filenames lookup for an ID
102+
// For preprocessor (if preprocessor==true).
103+
// TODO: design a common structure, that also works with #include, that
104+
// has these mappings for each file
105+
bool preprocessor = false;
106+
std::string in_filename;
107+
uint32_t current_line=0;
108+
std::vector<uint32_t> out_start0; // consecutive intervals in the output code
109+
std::vector<uint32_t> in_start0; // start + size in the original code
110+
std::vector<uint32_t> in_size0; // Size of the `in` interval
111+
std::vector<uint32_t> interval_type0; // 0 .... 1:1; 1 ... many to many;
112+
std::vector<uint32_t> in_newlines0; // position of all \n in the original code
113+
};
114+
std::vector<FileLocations> files;
115+
std::vector<uint32_t> file_ends; // position of all ends of files
116+
// For a given Location we use the `file_ends` and bisection to determine
117+
// the file (index) which the location is from. Then we use this index into
118+
// the `files` vector and use `in_newlines` and other information to
119+
// determine the line and column inside this file, and the `in_filename`
120+
// field to determine the filename. This happens when the diagnostic is
121+
// printed. The `pos_to_linecol` function below should be modified to
122+
// return line, column and the filename:
123+
//
124+
// void pos_to_linecol(uint32_t position, uint32_t &line, uint32_t &col,
125+
// std::string &filename) const;
114126

115127
// Converts a position in the output code to a position in the original code
116128
// Every character in the output code has a corresponding location in the
117129
// original code, so this function always succeeds
118130
uint32_t output_to_input_pos(uint32_t out_pos, bool show_last) const {
119-
if (out_start.size() == 0) return 0;
120-
uint32_t interval = bisection(out_start, out_pos)-1;
121-
uint32_t rel_pos = out_pos - out_start[interval];
122-
uint32_t in_pos = in_start[interval] + rel_pos;
123-
if (preprocessor) {
131+
if (files.back().out_start.size() == 0) return 0;
132+
uint32_t interval = bisection(files.back().out_start, out_pos)-1;
133+
uint32_t rel_pos = out_pos - files.back().out_start[interval];
134+
uint32_t in_pos = files.back().in_start[interval] + rel_pos;
135+
if (files.back().preprocessor) {
124136
// If preprocessor was used, do one more remapping
125-
uint32_t interval0 = bisection(out_start0, in_pos)-1;
126-
if (interval_type0[interval0] == 0) {
137+
uint32_t interval0 = bisection(files.back().out_start0, in_pos)-1;
138+
if (files.back().interval_type0[interval0] == 0) {
127139
// 1:1 interval
128-
uint32_t rel_pos0 = in_pos - out_start0[interval0];
129-
uint32_t in_pos0 = in_start0[interval0] + rel_pos0;
140+
uint32_t rel_pos0 = in_pos - files.back().out_start0[interval0];
141+
uint32_t in_pos0 = files.back().in_start0[interval0] + rel_pos0;
130142
return in_pos0;
131143
} else {
132144
// many to many interval
133145
uint32_t in_pos0;
134-
if (in_pos == out_start0[interval0+1]-1 || show_last) {
146+
if (in_pos == files.back().out_start0[interval0+1]-1 || show_last) {
135147
// The end of the interval in "out" code
136148
// Return the end of the interval in "in" code
137-
in_pos0 = in_start0[interval0]+in_size0[interval0]-1;
149+
in_pos0 = files.back().in_start0[interval0]+files.back().in_size0[interval0]-1;
138150
} else {
139151
// Otherwise return the beginning of the interval in "in"
140-
in_pos0 = in_start0[interval0];
152+
in_pos0 = files.back().in_start0[interval0];
141153
}
142154
return in_pos0;
143155
}
@@ -152,10 +164,10 @@ struct LocationManager {
152164
// `in_newlines` starts from 0
153165
void pos_to_linecol(uint32_t position, uint32_t &line, uint32_t &col) const {
154166
const std::vector<uint32_t> *newlines;
155-
if (preprocessor) {
156-
newlines = &in_newlines0;
167+
if (files.back().preprocessor) {
168+
newlines = &files.back().in_newlines0;
157169
} else {
158-
newlines = &in_newlines;
170+
newlines = &files.back().in_newlines;
159171
}
160172
int32_t interval = bisection(*newlines, position);
161173
if (interval >= 1 && position == (*newlines)[interval-1]) {
@@ -179,9 +191,9 @@ struct LocationManager {
179191

180192
void init_simple(const std::string &input) {
181193
uint32_t n = input.size();
182-
out_start = {0, n};
183-
in_start = {0, n};
184-
get_newlines(input, in_newlines);
194+
files.back().out_start = {0, n};
195+
files.back().in_start = {0, n};
196+
get_newlines(input, files.back().in_newlines);
185197
}
186198

187199
};

0 commit comments

Comments
 (0)