Skip to content

Commit 1b4213a

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

20 files changed

+479
-285
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ share/jupyter/kernels/fortran/kernel.json
6262
src/runtime/*.o.empty.c
6363
python_ast.py
6464
python_ast.h
65-
ser.txt
65+
input.txt
6666
integration_tests/py_*
6767
integration_tests/b1/*
6868
integration_tests/b2/*
@@ -72,6 +72,7 @@ integration_tests/b5/*
7272
integration_tests/b6/*
7373
integration_tests/_lpython-tmp-test-*
7474
inst/bin/*
75+
*.tmp
7576
*.tlog
7677
*.filters
7778
*.obj

src/bin/lpython.cpp

Lines changed: 233 additions & 137 deletions
Large diffs are not rendered by default.

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,15 @@ 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;
384-
lm.init_simple(LFortran::read_file(infile));
385-
lm.pos_to_linecol(lm.output_to_input_pos(loc_first, false), line, column);
383+
LocationManager::FileLocations fl;
384+
fl.in_filename = infile;
385+
lm.files.push_back(fl);
386+
std::string input = LFortran::read_file(infile);
387+
// std::cout << infile << "\n" << input << "\n";
388+
lm.init_simple(input);
389+
lm.file_ends.push_back(input.size());
390+
lm.pos_to_linecol(lm.output_to_input_pos(loc_first, false),
391+
line, column, fl.in_filename);
386392
}
387393

388394
template <typename T>

src/libasr/diagnostics.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,19 @@ 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(LocationManager &lm,
65+
const CompilerOptions &compiler_options) {
6666
std::string out;
6767
for (auto &d : this->diagnostics) {
6868
if (compiler_options.no_warnings && d.level != Level::Error) {
6969
continue;
7070
}
7171
if (compiler_options.error_format == "human") {
72-
out += render_diagnostic_human(d, input, lm,
73-
compiler_options.use_colors,
72+
out += render_diagnostic_human(d, lm, compiler_options.use_colors,
7473
compiler_options.show_stacktrace);
7574
if (&d != &this->diagnostics.back()) out += "\n";
7675
} else if (compiler_options.error_format == "short") {
77-
out += render_diagnostic_short(d, input, lm);
76+
out += render_diagnostic_short(d, lm);
7877
} else {
7978
throw LCompilersException("Error format not supported.");
8079
}
@@ -108,49 +107,48 @@ std::string get_line(std::string str, int n)
108107
return line;
109108
}
110109

111-
void populate_span(diag::Span &s, const LocationManager &lm,
112-
const std::string &input) {
110+
void populate_span(diag::Span &s, const LocationManager &lm) {
113111
lm.pos_to_linecol(lm.output_to_input_pos(s.loc.first, false),
114-
s.first_line, s.first_column);
112+
s.first_line, s.first_column, s.filename);
115113
lm.pos_to_linecol(lm.output_to_input_pos(s.loc.last, true),
116-
s.last_line, s.last_column);
117-
s.filename = lm.in_filename;
114+
s.last_line, s.last_column, s.filename);
115+
std::string input;
116+
read_file(s.filename, input);
117+
// std::cout << s.filename << "\n";
118118
for (uint32_t i = s.first_line; i <= s.last_line; i++) {
119119
s.source_code.push_back(get_line(input, i));
120120
}
121121
LFORTRAN_ASSERT(s.source_code.size() > 0)
122122
}
123123

124124
// Loop over all labels and their spans, populate all of them
125-
void populate_spans(diag::Diagnostic &d, const LocationManager &lm,
126-
const std::string &input) {
125+
void populate_spans(diag::Diagnostic &d, const LocationManager &lm) {
127126
for (auto &l : d.labels) {
128127
for (auto &s : l.spans) {
129-
populate_span(s, lm, input);
128+
populate_span(s, lm);
130129
}
131130
}
132131
}
133132

134133
// Fills Diagnostic with span details and renders it
135-
std::string render_diagnostic_human(Diagnostic &d, const std::string &input,
136-
const LocationManager &lm, bool use_colors, bool show_stacktrace) {
134+
std::string render_diagnostic_human(Diagnostic &d, const LocationManager &lm,
135+
bool use_colors, bool show_stacktrace) {
137136
std::string out;
138137
if (show_stacktrace) {
139138
out += error_stacktrace(d.stacktrace);
140139
}
141140
// Convert to line numbers and get source code strings
142-
populate_spans(d, lm, input);
141+
populate_spans(d, lm);
143142
// Render the message
144143
out += render_diagnostic_human(d, use_colors);
145144
return out;
146145
}
147146

148147
// Fills Diagnostic with span details and renders it
149-
std::string render_diagnostic_short(Diagnostic &d, const std::string &input,
150-
const LocationManager &lm) {
148+
std::string render_diagnostic_short(Diagnostic &d, const LocationManager &lm) {
151149
std::string out;
152150
// Convert to line numbers and get source code strings
153-
populate_spans(d, lm, input);
151+
populate_spans(d, lm);
154152
// Render the message
155153
out += render_diagnostic_short(d);
156154
return out;
@@ -178,7 +176,7 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) {
178176
std::string type_color = "";
179177
switch (d.level) {
180178
case (Level::Error):
181-
primary_color = red_bold;
179+
primary_color = red_bold;
182180
type_color = primary_color;
183181
switch (d.stage) {
184182
case (Stage::CPreprocessor):
@@ -205,17 +203,17 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) {
205203
}
206204
break;
207205
case (Level::Warning):
208-
primary_color = yellow_bold;
206+
primary_color = yellow_bold;
209207
type_color = primary_color;
210208
message_type = "warning";
211209
break;
212210
case (Level::Note):
213-
primary_color = bold;
211+
primary_color = bold;
214212
type_color = primary_color;
215213
message_type = "note";
216214
break;
217215
case (Level::Help):
218-
primary_color = bold;
216+
primary_color = bold;
219217
type_color = primary_color;
220218
message_type = "help";
221219
break;
@@ -286,6 +284,18 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) {
286284
}
287285
// and start a new one:
288286
s0 = s2;
287+
if (s0.filename != s.filename) {
288+
out << std::endl;
289+
// TODO: print the primary line+column here, not the first label:
290+
out << std::string(line_num_width, ' ') << blue_bold;
291+
out << "-->" << reset << " " << s0.filename << ":";
292+
out << s0.first_line << ":" << s0.first_column;
293+
if (s0.first_line != s0.last_line) {
294+
out << " - " << s0.last_line << ":" << s0.last_column;
295+
}
296+
out << std::endl;
297+
}
298+
289299
if (s0.first_line == s0.last_line) {
290300
out << std::string(line_num_width+1, ' ') << blue_bold << "|"
291301
<< reset << std::endl;

src/libasr/diagnostics.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,7 @@ struct Diagnostic {
113113
struct Diagnostics {
114114
std::vector<Diagnostic> diagnostics;
115115

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

119118
// Returns true iff diagnostics contains at least one error message
120119
bool has_error() const;
@@ -187,10 +186,9 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors);
187186
std::string render_diagnostic_short(const Diagnostic &d);
188187

189188
// Fills Diagnostic with span details and renders it
190-
std::string render_diagnostic_human(Diagnostic &d, const std::string &input,
191-
const LocationManager &lm, bool use_colors, bool show_stacktrace);
192-
std::string render_diagnostic_short(Diagnostic &d, const std::string &input,
193-
const LocationManager &lm);
189+
std::string render_diagnostic_human(Diagnostic &d, const LocationManager &lm,
190+
bool use_colors, bool show_stacktrace);
191+
std::string render_diagnostic_short(Diagnostic &d, const LocationManager &lm);
194192

195193
} // namespace diag
196194
} // namespace LFortran

src/libasr/location.h

Lines changed: 67 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <cstdint>
55
#include <vector>
6+
// #include <iostream>
67

78
namespace LFortran
89
{
@@ -94,50 +95,67 @@ struct LocationManager {
9495
//
9596
//
9697
//
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
98+
struct FileLocations {
99+
std::vector<uint32_t> out_start; // consecutive intervals in the output code
100+
std::vector<uint32_t> in_start; // start + size in the original code
101+
std::vector<uint32_t> in_newlines; // position of all \n in the original code
100102

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

115128
// Converts a position in the output code to a position in the original code
116129
// Every character in the output code has a corresponding location in the
117130
// original code, so this function always succeeds
118131
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) {
132+
// std::cout << "out: " << out_pos << "\n";
133+
uint32_t index = bisection(file_ends, out_pos);
134+
if (index == file_ends.size()) index -= 1;
135+
// std::cout << index << ":\n";
136+
if (files[index].out_start.size() == 0) return 0;
137+
uint32_t interval = bisection(files[index].out_start, out_pos)-1;
138+
uint32_t rel_pos = out_pos - files[index].out_start[interval];
139+
uint32_t in_pos = files[index].in_start[interval] + rel_pos;
140+
// std::cout << "in: "<< in_pos << "\n";
141+
if (files[index].preprocessor) {
124142
// If preprocessor was used, do one more remapping
125-
uint32_t interval0 = bisection(out_start0, in_pos)-1;
126-
if (interval_type0[interval0] == 0) {
143+
uint32_t interval0 = bisection(files[index].out_start0, in_pos)-1;
144+
if (files[index].interval_type0[interval0] == 0) {
127145
// 1:1 interval
128-
uint32_t rel_pos0 = in_pos - out_start0[interval0];
129-
uint32_t in_pos0 = in_start0[interval0] + rel_pos0;
146+
uint32_t rel_pos0 = in_pos - files[index].out_start0[interval0];
147+
uint32_t in_pos0 = files[index].in_start0[interval0] + rel_pos0;
130148
return in_pos0;
131149
} else {
132150
// many to many interval
133151
uint32_t in_pos0;
134-
if (in_pos == out_start0[interval0+1]-1 || show_last) {
152+
if (in_pos == files[index].out_start0[interval0+1]-1 || show_last) {
135153
// The end of the interval in "out" code
136154
// Return the end of the interval in "in" code
137-
in_pos0 = in_start0[interval0]+in_size0[interval0]-1;
155+
in_pos0 = files[index].in_start0[interval0]+files[index].in_size0[interval0]-1;
138156
} else {
139157
// Otherwise return the beginning of the interval in "in"
140-
in_pos0 = in_start0[interval0];
158+
in_pos0 = files[index].in_start0[interval0];
141159
}
142160
return in_pos0;
143161
}
@@ -150,12 +168,26 @@ struct LocationManager {
150168
// `position` starts from 0
151169
// `line` and `col` starts from 1
152170
// `in_newlines` starts from 0
153-
void pos_to_linecol(uint32_t position, uint32_t &line, uint32_t &col) const {
171+
void pos_to_linecol(uint32_t position, uint32_t &line, uint32_t &col,
172+
std::string &filename) const {
173+
uint32_t index = bisection(file_ends, position);
174+
if (index == file_ends.size()) index -= 1;
175+
// std::cout << position << ": Pos1\n";
176+
filename = files[index].in_filename;
177+
// std::cout << "----------------------------\n";
178+
// for (auto &x: file_ends) std::cout << x << "\n";
179+
// std::cout << "----------------------------\n";
180+
// std::cout << file_ends[index] << ": "<< file_ends[index - 1] << ": " << position - file_ends[index - 1] << "\n";
181+
if (index > 0) position -= file_ends[index - 1];
182+
// std::cout << index << "_\n";
183+
// std::cout << position << ": Pos2\n";
184+
// std::cout << filename << ": Name\n";
185+
// exit(0);
154186
const std::vector<uint32_t> *newlines;
155-
if (preprocessor) {
156-
newlines = &in_newlines0;
187+
if (files[index].preprocessor) {
188+
newlines = &files[index].in_newlines0;
157189
} else {
158-
newlines = &in_newlines;
190+
newlines = &files[index].in_newlines;
159191
}
160192
int32_t interval = bisection(*newlines, position);
161193
if (interval >= 1 && position == (*newlines)[interval-1]) {
@@ -179,9 +211,9 @@ struct LocationManager {
179211

180212
void init_simple(const std::string &input) {
181213
uint32_t n = input.size();
182-
out_start = {0, n};
183-
in_start = {0, n};
184-
get_newlines(input, in_newlines);
214+
files.back().out_start = {0, n};
215+
files.back().in_start = {0, n};
216+
get_newlines(input, files.back().in_newlines);
185217
}
186218

187219
};

src/libasr/lsp_interface.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace LFortran::LPython {
1111
uint32_t first_column;
1212
uint32_t last_line;
1313
uint32_t last_column;
14+
std::string filename;
1415
uint32_t severity;
1516
};
1617
struct document_symbols {
@@ -19,6 +20,7 @@ namespace LFortran::LPython {
1920
uint32_t first_column;
2021
uint32_t last_line;
2122
uint32_t last_column;
23+
std::string filename;
2224
};
2325

2426
} // namespace LFortran::Python

src/libasr/string_utils.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ std::string read_file(const std::string &filename)
9999
std::vector<char> bytes(filesize);
100100
ifs.read(&bytes[0], filesize);
101101

102-
return std::string(&bytes[0], filesize);
102+
std::string s(&bytes[0], filesize);
103+
s.erase( std::remove(s.begin(), s.end(), '\r'), s.end() );
104+
return s;
103105
}
104106

105107
std::string parent_path(const std::string &path) {

src/libasr/utils2.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ bool read_file(const std::string &filename, std::string &text)
2525
ifs.read(&bytes[0], filesize);
2626

2727
text = std::string(&bytes[0], filesize);
28+
text.erase( std::remove(text.begin(), text.end(), '\r'), text.end() );
2829
return true;
2930
}
3031

0 commit comments

Comments
 (0)