diff --git a/.gitignore b/.gitignore index 94846e03a5..3b4d8b2707 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,7 @@ share/jupyter/kernels/fortran/kernel.json src/runtime/*.o.empty.c python_ast.py python_ast.h -ser.txt +input.txt integration_tests/py_* integration_tests/b1/* integration_tests/b2/* @@ -72,6 +72,7 @@ integration_tests/b5/* integration_tests/b6/* integration_tests/_lpython-tmp-test-* inst/bin/* +*.tmp *.tlog *.filters *.obj diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 3405487964..d120ed9379 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -90,9 +90,15 @@ int emit_tokens(const std::string &infile, bool line_numbers, const CompilerOpti LFortran::diag::Diagnostics diagnostics; auto res = LFortran::tokens(al, input, diagnostics, &stypes, &locations); LFortran::LocationManager lm; - lm.in_filename = infile; - lm.init_simple(input); - std::cerr << diagnostics.render(input, lm, compiler_options); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } + std::cerr << diagnostics.render(lm, compiler_options); if (res.ok) { toks = res.result; } else { @@ -118,14 +124,18 @@ int emit_ast(const std::string &infile, Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); if (diagnostics.diagnostics.size() > 0) { LFortran::LocationManager lm; - lm.in_filename = infile; - // TODO: only read this once, and pass it as an argument to parse_python_file() - std::string input = LFortran::read_file(infile); - lm.init_simple(input); - std::cerr << diagnostics.render(input, lm, compiler_options); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } + std::cerr << diagnostics.render(lm, compiler_options); } if (!r.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -151,12 +161,17 @@ int emit_asr(const std::string &infile, Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; - std::string input = LFortran::read_file(infile); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } LFortran::Result r1 = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); - std::cerr << diagnostics.render(input, lm, compiler_options); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { return 1; } @@ -164,8 +179,9 @@ int emit_asr(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result - r = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); - std::cerr << diagnostics.render(input, lm, compiler_options); + r = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, + compiler_options, true, infile); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 2; @@ -193,12 +209,17 @@ int emit_cpp(const std::string &infile, Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; - std::string input = LFortran::read_file(infile); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); - std::cerr << diagnostics.render(input, lm, compiler_options); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { return 1; } @@ -206,8 +227,8 @@ int emit_cpp(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); - std::cerr << diagnostics.render(input, lm, compiler_options); + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 2; @@ -217,7 +238,7 @@ int emit_cpp(const std::string &infile, diagnostics.diagnostics.clear(); auto res = LFortran::asr_to_cpp(al, *asr, diagnostics, compiler_options.platform, 0); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!res.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 3; @@ -233,12 +254,17 @@ int emit_c(const std::string &infile, Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; - std::string input = LFortran::read_file(infile); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); - std::cerr << diagnostics.render(input, lm, compiler_options); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { return 1; } @@ -246,8 +272,8 @@ int emit_c(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); - std::cerr << diagnostics.render(input, lm, compiler_options); + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 2; @@ -257,7 +283,7 @@ int emit_c(const std::string &infile, diagnostics.diagnostics.clear(); auto res = LFortran::asr_to_c(al, *asr, diagnostics, compiler_options.platform, 0); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!res.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 3; @@ -273,12 +299,17 @@ int emit_wat(const std::string &infile, Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; - std::string input = LFortran::read_file(infile); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); - std::cerr << diagnostics.render(input, lm, compiler_options); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { return 1; } @@ -286,8 +317,8 @@ int emit_wat(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); - std::cerr << diagnostics.render(input, lm, compiler_options); + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 2; @@ -296,7 +327,7 @@ int emit_wat(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result> r2 = LFortran::asr_to_wasm_bytes_stream(*asr, al, diagnostics); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r2.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 3; @@ -304,7 +335,7 @@ int emit_wat(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result res = LFortran::wasm_to_wat(r2.result, al, diagnostics); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!res.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 4; @@ -320,16 +351,21 @@ int get_symbols (const std::string &infile, CompilerOptions &compiler_options) { Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; - LFortran::LocationManager lm; - lm.in_filename = infile; - std::string input = LFortran::read_file(infile); - lm.init_simple(input); + LFortran::LocationManager lm; + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } LFortran::Result r1 = LFortran::parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); if (r1.ok) { LFortran::LPython::AST::ast_t* ast = r1.result; LFortran::Result - x = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); + x = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); if (!x.ok) { std::cout << "{}\n"; return 0; @@ -342,13 +378,17 @@ int get_symbols (const std::string &infile, uint32_t last_line; uint32_t first_column; uint32_t last_column; - lm.pos_to_linecol(a.second->base.loc.first, first_line, first_column); - lm.pos_to_linecol(a.second->base.loc.last, last_line, last_column); + std::string filename; + lm.pos_to_linecol(a.second->base.loc.first, first_line, + first_column, filename); + lm.pos_to_linecol(a.second->base.loc.last, last_line, + last_column, filename); loc.first_column = first_column; loc.last_column = last_column; loc.first_line = first_line-1; loc.last_line = last_line-1; loc.symbol_name = symbol_name; + loc.filename = filename; symbol_lists.push_back(loc); } rapidjson::Document test_output(rapidjson::kArrayType); @@ -412,16 +452,21 @@ int get_errors (const std::string &infile, Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; - std::string input = LFortran::read_file(infile); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } LFortran::Result r1 = LFortran::parse_python_file(al, runtime_library_dir, infile, - diagnostics, compiler_options.new_parser); + diagnostics, 0, compiler_options.new_parser); if (r1.ok) { LFortran::LPython::AST::ast_t* ast = r1.result; LFortran::Result - r = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); + r = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); } std::vector diag_lists; LFortran::LPython::error_highlight h; @@ -437,12 +482,16 @@ int get_errors (const std::string &infile, uint32_t first_column; uint32_t last_line; uint32_t last_column; - lm.pos_to_linecol(span.loc.first, first_line, first_column); - lm.pos_to_linecol(span.loc.last, last_line, last_column); + std::string filename; + lm.pos_to_linecol(span.loc.first, first_line, first_column, + filename); + lm.pos_to_linecol(span.loc.last, last_line, last_column, + filename); h.first_column = first_column; h.last_column = last_column; h.first_line = first_line-1; h.last_line = last_line-1; + h.filename = filename; diag_lists.push_back(h); } } @@ -518,12 +567,17 @@ int emit_llvm(const std::string &infile, Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; - std::string input = LFortran::read_file(infile); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); - std::cerr << diagnostics.render(input, lm, compiler_options); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { return 1; } @@ -532,8 +586,8 @@ int emit_llvm(const std::string &infile, LFortran::LPython::AST::ast_t* ast = r.result; diagnostics.diagnostics.clear(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); - std::cerr << diagnostics.render(input, lm, compiler_options); + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 2; @@ -545,7 +599,7 @@ int emit_llvm(const std::string &infile, LFortran::PythonCompiler fe(compiler_options); LFortran::Result> res = fe.get_llvm3(*asr, pass_manager, diagnostics, infile); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!res.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return 3; @@ -565,19 +619,27 @@ int compile_python_to_object_file( Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; std::vector>times; - auto file_reading_start = std::chrono::high_resolution_clock::now(); - std::string input = LFortran::read_file(infile); - auto file_reading_end = std::chrono::high_resolution_clock::now(); - times.push_back(std::make_pair("File reading", std::chrono::duration(file_reading_end - file_reading_start).count())); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + + auto file_reading_start = std::chrono::high_resolution_clock::now(); + std::string input = LFortran::read_file(infile); + auto file_reading_end = std::chrono::high_resolution_clock::now(); + times.push_back(std::make_pair("File reading", std::chrono::duration< + double, std::milli>(file_reading_end - file_reading_start).count())); + + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } auto parsing_start = std::chrono::high_resolution_clock::now(); LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); auto parsing_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("Parsing", std::chrono::duration(parsing_end - parsing_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { print_time_report(times, time_report); return 1; @@ -588,12 +650,12 @@ int compile_python_to_object_file( diagnostics.diagnostics.clear(); auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, !(arg_c && compiler_options.disable_main), infile); auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("AST to ASR", std::chrono::duration(ast_to_asr_end - ast_to_asr_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) print_time_report(times, time_report); @@ -617,7 +679,7 @@ int compile_python_to_object_file( res = fe.get_llvm3(*asr, pass_manager, diagnostics, infile); auto asr_to_llvm_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("ASR to LLVM", std::chrono::duration(asr_to_llvm_end - asr_to_llvm_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!res.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) print_time_report(times, time_report); @@ -649,19 +711,27 @@ int compile_to_binary_wasm( Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; std::vector>times; - auto file_reading_start = std::chrono::high_resolution_clock::now(); - std::string input = LFortran::read_file(infile); - auto file_reading_end = std::chrono::high_resolution_clock::now(); - times.push_back(std::make_pair("File reading", std::chrono::duration(file_reading_end - file_reading_start).count())); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + + auto file_reading_start = std::chrono::high_resolution_clock::now(); + std::string input = LFortran::read_file(infile); + auto file_reading_end = std::chrono::high_resolution_clock::now(); + times.push_back(std::make_pair("File reading", std::chrono::duration + (file_reading_end - file_reading_start).count())); + + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } auto parsing_start = std::chrono::high_resolution_clock::now(); LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); auto parsing_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("Parsing", std::chrono::duration(parsing_end - parsing_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { print_time_report(times, time_report); return 1; @@ -672,10 +742,10 @@ int compile_to_binary_wasm( diagnostics.diagnostics.clear(); auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("AST to ASR", std::chrono::duration(ast_to_asr_end - ast_to_asr_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) print_time_report(times, time_report); @@ -695,7 +765,7 @@ int compile_to_binary_wasm( LFortran::Result res = LFortran::asr_to_wasm(*asr, al, outfile, time_report, diagnostics); auto asr_to_wasm_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("ASR to WASM", std::chrono::duration(asr_to_wasm_end - asr_to_wasm_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); print_time_report(times, time_report); if (!res.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -714,19 +784,27 @@ int compile_to_binary_x86( Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; std::vector>times; - auto file_reading_start = std::chrono::high_resolution_clock::now(); - std::string input = LFortran::read_file(infile); - auto file_reading_end = std::chrono::high_resolution_clock::now(); - times.push_back(std::make_pair("File reading", std::chrono::duration(file_reading_end - file_reading_start).count())); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + + auto file_reading_start = std::chrono::high_resolution_clock::now(); + std::string input = LFortran::read_file(infile); + auto file_reading_end = std::chrono::high_resolution_clock::now(); + times.push_back(std::make_pair("File reading", std::chrono::duration + (file_reading_end - file_reading_start).count())); + + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } auto parsing_start = std::chrono::high_resolution_clock::now(); LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); auto parsing_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("Parsing", std::chrono::duration(parsing_end - parsing_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { print_time_report(times, time_report); return 1; @@ -737,10 +815,10 @@ int compile_to_binary_x86( diagnostics.diagnostics.clear(); auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("AST to ASR", std::chrono::duration(ast_to_asr_end - ast_to_asr_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) print_time_report(times, time_report); @@ -760,7 +838,7 @@ int compile_to_binary_x86( LFortran::Result r3 = LFortran::asr_to_x86(*asr, al, outfile, time_report, diagnostics); auto asr_to_x86_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("ASR to X86", std::chrono::duration(asr_to_x86_end - asr_to_x86_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); print_time_report(times, time_report); if (!r3.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -779,19 +857,27 @@ int compile_to_binary_wasm_to_x86( Allocator al(4*1024); LFortran::diag::Diagnostics diagnostics; LFortran::LocationManager lm; - lm.in_filename = infile; std::vector>times; - auto file_reading_start = std::chrono::high_resolution_clock::now(); - std::string input = LFortran::read_file(infile); - auto file_reading_end = std::chrono::high_resolution_clock::now(); - times.push_back(std::make_pair("File reading", std::chrono::duration(file_reading_end - file_reading_start).count())); - lm.init_simple(input); + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + + auto file_reading_start = std::chrono::high_resolution_clock::now(); + std::string input = LFortran::read_file(infile); + auto file_reading_end = std::chrono::high_resolution_clock::now(); + times.push_back(std::make_pair("File reading", std::chrono::duration + (file_reading_end - file_reading_start).count())); + + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + } auto parsing_start = std::chrono::high_resolution_clock::now(); LFortran::Result r = parse_python_file( - al, runtime_library_dir, infile, diagnostics, compiler_options.new_parser); + al, runtime_library_dir, infile, diagnostics, 0, compiler_options.new_parser); auto parsing_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("Parsing", std::chrono::duration(parsing_end - parsing_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r.ok) { print_time_report(times, time_report); return 1; @@ -802,10 +888,10 @@ int compile_to_binary_wasm_to_x86( diagnostics.diagnostics.clear(); auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); LFortran::Result - r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, compiler_options, true, infile); + r1 = LFortran::LPython::python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, true, infile); auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("AST to ASR", std::chrono::duration(ast_to_asr_end - ast_to_asr_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) print_time_report(times, time_report); @@ -825,7 +911,7 @@ int compile_to_binary_wasm_to_x86( LFortran::Result> r3 = LFortran::asr_to_wasm_bytes_stream(*asr, al, diagnostics); auto asr_to_wasm_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("ASR to WASM", std::chrono::duration(asr_to_wasm_end - asr_to_wasm_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); if (!r3.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) print_time_report(times, time_report); @@ -837,7 +923,7 @@ int compile_to_binary_wasm_to_x86( LFortran::Result res = LFortran::wasm_to_x86(r3.result, al, outfile, time_report, diagnostics); auto wasm_to_x86_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("WASM to X86", std::chrono::duration(wasm_to_x86_end - wasm_to_x86_start).count())); - std::cerr << diagnostics.render(input, lm, compiler_options); + std::cerr << diagnostics.render(lm, compiler_options); print_time_report(times, time_report); if (!res.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -1036,9 +1122,17 @@ namespace wasm { compiler_options.use_colors = true; \ compiler_options.indent = true; \ Allocator al(4*1024); \ - LFortran::LocationManager lm; \ LFortran::diag::Diagnostics diagnostics; \ - lm.in_filename = "input"; + LFortran::LocationManager lm; \ + { \ + LFortran::LocationManager::FileLocations fl; \ + fl.in_filename = "input.txt"; \ + std::ofstream out("input.txt"); \ + out << input; \ + lm.files.push_back(fl); \ + lm.init_simple(std::string(input)); \ + lm.file_ends.push_back(strlen(input)); \ + } @@ -1049,8 +1143,8 @@ extern "C" { // using extern "C" to prevent function name mangling EMSCRIPTEN_KEEPALIVE char* emit_ast_from_source(char *input) { INITIALIZE_VARS; lm.init_simple(input); - LFortran::Result ast = LFortran::parse(al, input, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + LFortran::Result ast = LFortran::parse(al, input, 0, diagnostics); + out = diagnostics.render(lm, compiler_options); if (ast.ok) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; out += LFortran::LPython::pickle_python(*casted_ast, @@ -1062,13 +1156,13 @@ EMSCRIPTEN_KEEPALIVE char* emit_ast_from_source(char *input) { EMSCRIPTEN_KEEPALIVE char* emit_asr_from_source(char *input) { INITIALIZE_VARS; lm.init_simple(input); - LFortran::Result ast = LFortran::parse(al, input, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + LFortran::Result ast = LFortran::parse(al, input, 0, diagnostics); + out = diagnostics.render(lm, compiler_options); if (ast.ok) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result - asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, compiler_options, true, "input"); - out = diagnostics.render(input, lm, compiler_options); + asr = LFortran::LPython::python_ast_to_asr(al, lm, *casted_ast, diagnostics, compiler_options, true, "input"); + out = diagnostics.render(lm, compiler_options); if (asr.ok) { out += LFortran::pickle(*asr.result, compiler_options.use_colors, compiler_options.indent, false /* with_intrinsic_modules */); @@ -1080,21 +1174,21 @@ EMSCRIPTEN_KEEPALIVE char* emit_asr_from_source(char *input) { EMSCRIPTEN_KEEPALIVE char* emit_wat_from_source(char *input) { INITIALIZE_VARS; lm.init_simple(input); - LFortran::Result ast = LFortran::parse(al, input, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + LFortran::Result ast = LFortran::parse(al, input, 0, diagnostics); + out = diagnostics.render(lm, compiler_options); if (ast.ok) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result - asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, compiler_options, true, "input"); - out = diagnostics.render(input, lm, compiler_options); + asr = LFortran::LPython::python_ast_to_asr(al, lm, *casted_ast, diagnostics, compiler_options, true, "input"); + out = diagnostics.render(lm, compiler_options); if (asr.ok) { LFortran::Result> wasm = LFortran::asr_to_wasm_bytes_stream(*asr.result, al, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + out = diagnostics.render(lm, compiler_options); if (wasm.ok) { LFortran::Result wat = LFortran::wasm_to_wat(wasm.result, al, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + out = diagnostics.render(lm, compiler_options); if (wat.ok) { out += wat.result; } @@ -1107,17 +1201,17 @@ EMSCRIPTEN_KEEPALIVE char* emit_wat_from_source(char *input) { EMSCRIPTEN_KEEPALIVE char* emit_cpp_from_source(char *input) { INITIALIZE_VARS; lm.init_simple(input); - LFortran::Result ast = LFortran::parse(al, input, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + LFortran::Result ast = LFortran::parse(al, input, 0, diagnostics); + out = diagnostics.render(lm, compiler_options); if (ast.ok) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result - asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, compiler_options, true, "input"); - out = diagnostics.render(input, lm, compiler_options); + asr = LFortran::LPython::python_ast_to_asr(al, lm, *casted_ast, diagnostics, compiler_options, true, "input"); + out = diagnostics.render(lm, compiler_options); if (asr.ok) { auto res = LFortran::asr_to_cpp(al, *asr.result, diagnostics, compiler_options.platform, 0); - out = diagnostics.render(input, lm, compiler_options); + out = diagnostics.render(lm, compiler_options); if (res.ok) { out += res.result; } @@ -1129,7 +1223,7 @@ EMSCRIPTEN_KEEPALIVE char* emit_cpp_from_source(char *input) { // EMSCRIPTEN_KEEPALIVE char* emit_c_from_source(char *input) { // INITIALIZE_VARS; // LFortran::Result r = fe.get_c(input, lm, diagnostics, 1); -// out = diagnostics.render(input, lm, compiler_options); +// out = diagnostics.render(lm, compiler_options); // if (r.ok) { out += r.result; } // return &out[0]; // } @@ -1137,7 +1231,7 @@ EMSCRIPTEN_KEEPALIVE char* emit_cpp_from_source(char *input) { // EMSCRIPTEN_KEEPALIVE char* emit_py_from_source(char *input) { // INITIALIZE_VARS; // LFortran::Result r = fe.get_py(input, lm, diagnostics); -// out = diagnostics.render(input, lm, compiler_options); +// out = diagnostics.render(lm, compiler_options); // if (r.ok) { out += r.result; } // return &out[0]; // } @@ -1145,17 +1239,17 @@ EMSCRIPTEN_KEEPALIVE char* emit_cpp_from_source(char *input) { EMSCRIPTEN_KEEPALIVE char* emit_wasm_from_source(char *input) { INITIALIZE_VARS; lm.init_simple(input); - LFortran::Result ast = LFortran::parse(al, input, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + LFortran::Result ast = LFortran::parse(al, input, 0, diagnostics); + out = diagnostics.render(lm, compiler_options); if (ast.ok) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result - asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, compiler_options, true, "input"); - out = diagnostics.render(input, lm, compiler_options); + asr = LFortran::LPython::python_ast_to_asr(al, lm, *casted_ast, diagnostics, compiler_options, true, "input"); + out = diagnostics.render(lm, compiler_options); if (asr.ok) { LFortran::Result> wasm = LFortran::asr_to_wasm_bytes_stream(*asr.result, al, diagnostics); - out = diagnostics.render(input, lm, compiler_options); + out = diagnostics.render(lm, compiler_options); if (wasm.ok) { out = "0"; // exit code for (size_t i = 0; i < wasm.result.size(); i++) { @@ -1166,7 +1260,7 @@ EMSCRIPTEN_KEEPALIVE char* emit_wasm_from_source(char *input) { } } out = "1"; // non-zero exit code - out += "," + diagnostics.render(input, lm, compiler_options); + out += "," + diagnostics.render(lm, compiler_options); return &out[0]; } diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 5fe41cddb6..a30f8a53ef 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -375,9 +375,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor void debug_get_line_column(const uint32_t &loc_first, uint32_t &line, uint32_t &column) { LocationManager lm; - lm.in_filename = infile; - lm.init_simple(LFortran::read_file(infile)); - lm.pos_to_linecol(lm.output_to_input_pos(loc_first, false), line, column); + LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.init_simple(input); + lm.file_ends.push_back(input.size()); + lm.pos_to_linecol(lm.output_to_input_pos(loc_first, false), + line, column, fl.in_filename); } template diff --git a/src/libasr/diagnostics.cpp b/src/libasr/diagnostics.cpp index 0fba593f64..e1cd213fd2 100644 --- a/src/libasr/diagnostics.cpp +++ b/src/libasr/diagnostics.cpp @@ -61,20 +61,19 @@ bool Diagnostics::has_error() const { return false; } -std::string Diagnostics::render(const std::string &input, - const LocationManager &lm, const CompilerOptions &compiler_options) { +std::string Diagnostics::render(LocationManager &lm, + const CompilerOptions &compiler_options) { std::string out; for (auto &d : this->diagnostics) { if (compiler_options.no_warnings && d.level != Level::Error) { continue; } if (compiler_options.error_format == "human") { - out += render_diagnostic_human(d, input, lm, - compiler_options.use_colors, + out += render_diagnostic_human(d, lm, compiler_options.use_colors, compiler_options.show_stacktrace); if (&d != &this->diagnostics.back()) out += "\n"; } else if (compiler_options.error_format == "short") { - out += render_diagnostic_short(d, input, lm); + out += render_diagnostic_short(d, lm); } else { throw LCompilersException("Error format not supported."); } @@ -119,13 +118,13 @@ std::string get_line(std::string str, int n) return line; } -void populate_span(diag::Span &s, const LocationManager &lm, - const std::string &input) { +void populate_span(diag::Span &s, const LocationManager &lm) { lm.pos_to_linecol(lm.output_to_input_pos(s.loc.first, false), - s.first_line, s.first_column); + s.first_line, s.first_column, s.filename); lm.pos_to_linecol(lm.output_to_input_pos(s.loc.last, true), - s.last_line, s.last_column); - s.filename = lm.in_filename; + s.last_line, s.last_column, s.filename); + std::string input; + read_file(s.filename, input); for (uint32_t i = s.first_line; i <= s.last_line; i++) { s.source_code.push_back(get_line(input, i)); } @@ -133,35 +132,33 @@ void populate_span(diag::Span &s, const LocationManager &lm, } // Loop over all labels and their spans, populate all of them -void populate_spans(diag::Diagnostic &d, const LocationManager &lm, - const std::string &input) { +void populate_spans(diag::Diagnostic &d, const LocationManager &lm) { for (auto &l : d.labels) { for (auto &s : l.spans) { - populate_span(s, lm, input); + populate_span(s, lm); } } } // Fills Diagnostic with span details and renders it -std::string render_diagnostic_human(Diagnostic &d, const std::string &input, - const LocationManager &lm, bool use_colors, bool show_stacktrace) { +std::string render_diagnostic_human(Diagnostic &d, const LocationManager &lm, + bool use_colors, bool show_stacktrace) { std::string out; if (show_stacktrace) { out += error_stacktrace(d.stacktrace); } // Convert to line numbers and get source code strings - populate_spans(d, lm, input); + populate_spans(d, lm); // Render the message out += render_diagnostic_human(d, use_colors); return out; } // Fills Diagnostic with span details and renders it -std::string render_diagnostic_short(Diagnostic &d, const std::string &input, - const LocationManager &lm) { +std::string render_diagnostic_short(Diagnostic &d, const LocationManager &lm) { std::string out; // Convert to line numbers and get source code strings - populate_spans(d, lm, input); + populate_spans(d, lm); // Render the message out += render_diagnostic_short(d); return out; @@ -245,11 +242,24 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) { } // and start a new one: s0 = s2; + if (s0.filename != s.filename) { + out << std::endl; + // TODO: print the primary line+column here, not the first label: + out << std::string(line_num_width, ' ') << blue_bold; + out << "-->" << reset << " " << s0.filename << ":"; + out << s0.first_line << ":" << s0.first_column; + if (s0.first_line != s0.last_line) { + out << " - " << s0.last_line << ":" << s0.last_column; + } + out << std::endl; + } + if (s0.first_line == s0.last_line) { out << std::string(line_num_width+1, ' ') << blue_bold << "|" << reset << std::endl; std::string line = s0.source_code[0]; std::replace(std::begin(line), std::end(line), '\t', ' '); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); out << blue_bold << std::setw(line_num_width) << std::to_string(s0.first_line) << " |" << reset << " " << line << std::endl; @@ -263,6 +273,7 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) { << reset << std::endl; std::string line = s0.source_code[0]; std::replace(std::begin(line), std::end(line), '\t', ' '); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); out << blue_bold << std::setw(line_num_width) << std::to_string(s0.first_line) << " |" << reset << " " << " " + line << std::endl; @@ -281,6 +292,7 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors) { << reset << std::endl; line = s0.source_code[s0.source_code.size()-1]; std::replace(std::begin(line), std::end(line), '\t', ' '); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); out << blue_bold << std::setw(line_num_width) << std::to_string(s0.last_line) << " |" << reset << " " << " " + line << std::endl; diff --git a/src/libasr/diagnostics.h b/src/libasr/diagnostics.h index 9f79eba86c..4bef0495cd 100644 --- a/src/libasr/diagnostics.h +++ b/src/libasr/diagnostics.h @@ -115,9 +115,7 @@ struct Diagnostic { struct Diagnostics { std::vector diagnostics; - // Render nice error messages using all the information we have - std::string render(const std::string &input, - const LocationManager &lm, const CompilerOptions &compiler_options); + std::string render(LocationManager &lm, const CompilerOptions &compiler_options); // Renders the error message using only the information in Diagnostics std::string render2(); @@ -214,10 +212,9 @@ std::string render_diagnostic_human(const Diagnostic &d, bool use_colors); std::string render_diagnostic_short(const Diagnostic &d); // Fills Diagnostic with span details and renders it -std::string render_diagnostic_human(Diagnostic &d, const std::string &input, - const LocationManager &lm, bool use_colors, bool show_stacktrace); -std::string render_diagnostic_short(Diagnostic &d, const std::string &input, - const LocationManager &lm); +std::string render_diagnostic_human(Diagnostic &d, const LocationManager &lm, + bool use_colors, bool show_stacktrace); +std::string render_diagnostic_short(Diagnostic &d, const LocationManager &lm); /** * @brief Convert diagnostic `Level` i.e. severity to string and color accordingly. * diff --git a/src/libasr/location.h b/src/libasr/location.h index a38d8175ce..de43b5cf34 100644 --- a/src/libasr/location.h +++ b/src/libasr/location.h @@ -94,50 +94,64 @@ struct LocationManager { // // // - std::vector out_start; // consecutive intervals in the output code - std::vector in_start; // start + size in the original code - std::vector in_newlines; // position of all \n in the original code + struct FileLocations { + std::vector out_start; // consecutive intervals in the output code + std::vector in_start; // start + size in the original code + std::vector in_newlines; // position of all \n in the original code - // For preprocessor (if preprocessor==true). - // TODO: design a common structure, that also works with #include, that - // has these mappings for each file - bool preprocessor = false; - std::string in_filename; - uint32_t current_line=0; - std::vector out_start0; // consecutive intervals in the output code - std::vector in_start0; // start + size in the original code - std::vector in_size0; // Size of the `in` interval - std::vector interval_type0; // 0 .... 1:1; 1 ... many to many; - std::vector in_newlines0; // position of all \n in the original code -// std::vector filename_id; // file name for each interval, ID -// std::vector filenames; // filenames lookup for an ID + // For preprocessor (if preprocessor==true). + // TODO: design a common structure, that also works with #include, that + // has these mappings for each file + bool preprocessor = false; + std::string in_filename; + uint32_t current_line=0; + std::vector out_start0; // consecutive intervals in the output code + std::vector in_start0; // start + size in the original code + std::vector in_size0; // Size of the `in` interval + std::vector interval_type0; // 0 .... 1:1; 1 ... many to many; + std::vector in_newlines0; // position of all \n in the original code + }; + std::vector files; + // Location is continued for the imported files, i.e.,if the new file is + // imported then the location starts from the size of the previous file. + // For example: file_ends = [120, 200, 350] + std::vector file_ends; // position of all ends of files + // For a given Location, we use the `file_ends` and `bisection` to determine + // the file (files' index), which the location is from. Then we use this index into + // the `files` vector and use `in_newlines` and other information to + // determine the line and column inside this file, and the `in_filename` + // field to determine the filename. This happens when the diagnostic is + // printed. // Converts a position in the output code to a position in the original code // Every character in the output code has a corresponding location in the // original code, so this function always succeeds uint32_t output_to_input_pos(uint32_t out_pos, bool show_last) const { - if (out_start.size() == 0) return 0; - uint32_t interval = bisection(out_start, out_pos)-1; - uint32_t rel_pos = out_pos - out_start[interval]; - uint32_t in_pos = in_start[interval] + rel_pos; - if (preprocessor) { + // Determine where the error is from using position, i.e., loc + uint32_t index = bisection(file_ends, out_pos); + if (index == file_ends.size()) index -= 1; + if (files[index].out_start.size() == 0) return 0; + uint32_t interval = bisection(files[index].out_start, out_pos)-1; + uint32_t rel_pos = out_pos - files[index].out_start[interval]; + uint32_t in_pos = files[index].in_start[interval] + rel_pos; + if (files[index].preprocessor) { // If preprocessor was used, do one more remapping - uint32_t interval0 = bisection(out_start0, in_pos)-1; - if (interval_type0[interval0] == 0) { + uint32_t interval0 = bisection(files[index].out_start0, in_pos)-1; + if (files[index].interval_type0[interval0] == 0) { // 1:1 interval - uint32_t rel_pos0 = in_pos - out_start0[interval0]; - uint32_t in_pos0 = in_start0[interval0] + rel_pos0; + uint32_t rel_pos0 = in_pos - files[index].out_start0[interval0]; + uint32_t in_pos0 = files[index].in_start0[interval0] + rel_pos0; return in_pos0; } else { // many to many interval uint32_t in_pos0; - if (in_pos == out_start0[interval0+1]-1 || show_last) { + if (in_pos == files[index].out_start0[interval0+1]-1 || show_last) { // The end of the interval in "out" code // Return the end of the interval in "in" code - in_pos0 = in_start0[interval0]+in_size0[interval0]-1; + in_pos0 = files[index].in_start0[interval0]+files[index].in_size0[interval0]-1; } else { // Otherwise return the beginning of the interval in "in" - in_pos0 = in_start0[interval0]; + in_pos0 = files[index].in_start0[interval0]; } return in_pos0; } @@ -150,12 +164,19 @@ struct LocationManager { // `position` starts from 0 // `line` and `col` starts from 1 // `in_newlines` starts from 0 - void pos_to_linecol(uint32_t position, uint32_t &line, uint32_t &col) const { + void pos_to_linecol(uint32_t position, uint32_t &line, uint32_t &col, + std::string &filename) const { + // Determine where the error is from using position, i.e., loc + uint32_t index = bisection(file_ends, position); + if (index == file_ends.size()) index -= 1; + filename = files[index].in_filename; + // Get the actual location by subtracting the previous file size. + if (index > 0) position -= file_ends[index - 1]; const std::vector *newlines; - if (preprocessor) { - newlines = &in_newlines0; + if (files[index].preprocessor) { + newlines = &files[index].in_newlines0; } else { - newlines = &in_newlines; + newlines = &files[index].in_newlines; } int32_t interval = bisection(*newlines, position); if (interval >= 1 && position == (*newlines)[interval-1]) { @@ -179,9 +200,9 @@ struct LocationManager { void init_simple(const std::string &input) { uint32_t n = input.size(); - out_start = {0, n}; - in_start = {0, n}; - get_newlines(input, in_newlines); + files.back().out_start = {0, n}; + files.back().in_start = {0, n}; + get_newlines(input, files.back().in_newlines); } }; diff --git a/src/libasr/lsp_interface.h b/src/libasr/lsp_interface.h index e6f4afb4d7..1b16564eab 100644 --- a/src/libasr/lsp_interface.h +++ b/src/libasr/lsp_interface.h @@ -11,6 +11,7 @@ namespace LFortran::LPython { uint32_t first_column; uint32_t last_line; uint32_t last_column; + std::string filename; uint32_t severity; }; struct document_symbols { @@ -19,6 +20,7 @@ namespace LFortran::LPython { uint32_t first_column; uint32_t last_line; uint32_t last_column; + std::string filename; }; } // namespace LFortran::Python diff --git a/src/lpython/parser/parser.cpp b/src/lpython/parser/parser.cpp index a5991564d6..237614a3ef 100644 --- a/src/lpython/parser/parser.cpp +++ b/src/lpython/parser/parser.cpp @@ -15,11 +15,11 @@ namespace LFortran { Result parse(Allocator &al, const std::string &s, - diag::Diagnostics &diagnostics) + uint32_t prev_loc, diag::Diagnostics &diagnostics) { Parser p(al, diagnostics); try { - p.parse(s); + p.parse(s, prev_loc); } catch (const parser_local::TokenizerError &e) { Error error; diagnostics.diagnostics.push_back(e.d); @@ -42,7 +42,7 @@ Result parse(Allocator &al, const std::string &s, p.result.p, p.result.size(), p.type_ignore.p, p.type_ignore.size()); } -void Parser::parse(const std::string &input) +void Parser::parse(const std::string &input, uint32_t prev_loc) { inp = input; if (inp.size() > 0) { @@ -50,7 +50,7 @@ void Parser::parse(const std::string &input) } else { inp.append("\n"); } - m_tokenizer.set_string(inp); + m_tokenizer.set_string(inp, prev_loc); if (yyparse(*this) == 0) { return; } @@ -116,13 +116,14 @@ Result parse_python_file(Allocator &al, const std::string &/*runtime_library_dir*/, const std::string &infile, diag::Diagnostics &diagnostics, + uint32_t prev_loc, bool new_parser) { LPython::AST::ast_t* ast; // We will be using the new parser from now on new_parser = true; LFORTRAN_ASSERT(new_parser) std::string input = read_file(infile); - Result res = parse(al, input, diagnostics); + Result res = parse(al, input, prev_loc, diagnostics); if (res.ok) { ast = (LPython::AST::ast_t*)res.result; } else { diff --git a/src/lpython/parser/parser.h b/src/lpython/parser/parser.h index 9149f2f106..9eade9bdef 100644 --- a/src/lpython/parser/parser.h +++ b/src/lpython/parser/parser.h @@ -26,21 +26,21 @@ class Parser type_ignore.reserve(al, 4); } - void parse(const std::string &input); + void parse(const std::string &input, uint32_t prev_loc); void handle_yyerror(const Location &loc, const std::string &msg); }; // Parses Python code to AST Result parse(Allocator &al, - const std::string &s, + const std::string &s, uint32_t prev_loc, diag::Diagnostics &diagnostics); Result parse_python_file(Allocator &al, const std::string &runtime_library_dir, const std::string &infile, diag::Diagnostics &diagnostics, - bool new_parser); + uint32_t prev_loc, bool new_parser); } // namespace LFortran diff --git a/src/lpython/parser/tokenizer.h b/src/lpython/parser/tokenizer.h index 3d3966b0c8..2539287e03 100644 --- a/src/lpython/parser/tokenizer.h +++ b/src/lpython/parser/tokenizer.h @@ -18,6 +18,7 @@ class Tokenizer unsigned char *cur_line; unsigned int line_num; unsigned char *string_start; + uint32_t prev_loc; // The previous file ended at this location. int last_token=-1; @@ -34,7 +35,7 @@ class Tokenizer public: // Set the string to tokenize. The caller must ensure `str` will stay valid // as long as `lex` is being called. - void set_string(const std::string &str); + void set_string(const std::string &str, uint32_t prev_loc_); // Get next token. Token ID is returned as function result, the semantic // value is put into `yylval`. @@ -71,8 +72,8 @@ class Tokenizer // Return the current token's location void token_loc(Location &loc) const { - loc.first = tok-string_start; - loc.last = cur-string_start-1; + loc.first = prev_loc + (tok-string_start); + loc.last = prev_loc + (cur-string_start-1); } void record_paren(Location &loc, char c); diff --git a/src/lpython/parser/tokenizer.re b/src/lpython/parser/tokenizer.re index 8915d384ec..1d11a14b24 100644 --- a/src/lpython/parser/tokenizer.re +++ b/src/lpython/parser/tokenizer.re @@ -122,7 +122,7 @@ void lex_imag(Allocator &al, const unsigned char *s, } } -void Tokenizer::set_string(const std::string &str) +void Tokenizer::set_string(const std::string &str, uint32_t prev_loc_) { // The input string must be NULL terminated, otherwise the tokenizer will // not detect the end of string. After C++11, the std::string is guaranteed @@ -130,6 +130,7 @@ void Tokenizer::set_string(const std::string &str) LFORTRAN_ASSERT(str[str.size()] == '\0'); cur = (unsigned char *)(&str[0]); string_start = cur; + prev_loc = prev_loc_; cur_line = cur; line_num = 1; } @@ -777,7 +778,7 @@ Result> tokens(Allocator &al, const std::string &input, std::vector *locations) { Tokenizer t; - t.set_string(input); + t.set_string(input, 0); std::vector tst; int token = yytokentype::END_OF_FILE + 1; // Something different from EOF while (token != yytokentype::END_OF_FILE) { diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index fc01941b90..9f4630a052 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -241,34 +241,35 @@ bool set_module_path(std::string infile0, std::vector &rl_path, } ASR::TranslationUnit_t* compile_module_till_asr(Allocator& al, - std::vector &rl_path, std::string infile, - const Location &loc, - const std::function err, - bool allow_implicit_casting) { - // TODO: diagnostic should be an argument to this function - diag::Diagnostics diagnostics; + std::vector &rl_path, std::string infile, + const Location &loc, diag::Diagnostics &diagnostics, LocationManager &lm, + const std::function err, + bool allow_implicit_casting) { + { + LFortran::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + std::string input = LFortran::read_file(infile); + lm.file_ends.push_back(lm.file_ends.back() + input.size()); + lm.init_simple(input); + } Result r = parse_python_file(al, rl_path[0], infile, - diagnostics, false); + diagnostics, lm.file_ends.end()[-2], false); if (!r.ok) { err("The file '" + infile + "' failed to parse", loc); } LFortran::LPython::AST::ast_t* ast = r.result; // Convert the module from AST to ASR - LFortran::LocationManager lm; - lm.in_filename = infile; LFortran::CompilerOptions compiler_options; compiler_options.disable_main = true; compiler_options.symtab_only = false; - Result r2 = python_ast_to_asr(al, *ast, + Result r2 = python_ast_to_asr(al, lm, *ast, diagnostics, compiler_options, false, infile, allow_implicit_casting); // TODO: Uncomment once a check is added for ensuring // that module.py file hasn't changed between // builds. // save_pyc_files(*r2.result, infile + "c"); - std::string input; - read_file(infile, input); - std::cerr << diagnostics.render(input, lm, compiler_options); if (!r2.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) return nullptr; // Error @@ -294,7 +295,8 @@ void fill_module_dependencies(SymbolTable* symtab, std::set& mod_de ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, const std::string &module_name, - const Location &loc, bool intrinsic, + const Location &loc, diag::Diagnostics &diagnostics, + LocationManager &lm, bool intrinsic, std::vector &rl_path, bool <ypes, bool& enum_py, const std::function err, @@ -347,7 +349,19 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, if (ltypes) return nullptr; if( compile_module ) { - mod1 = compile_module_till_asr(al, rl_path, infile, loc, err, allow_implicit_casting); + diagnostics.add(diag::Diagnostic( + "The module '" + module_name + "' cannot be loaded", + diag::Level::Warning, diag::Stage::Semantic, { + diag::Label("imported here", {loc}) + }) + ); + mod1 = compile_module_till_asr(al, rl_path, infile, loc, diagnostics, + lm, err, allow_implicit_casting); + if (mod1 == nullptr) { + throw SemanticAbort(); + } else { + diagnostics.diagnostics.pop_back(); + } } // insert into `symtab` @@ -493,6 +507,7 @@ class CommonVisitor : public AST::BaseVisitor { std::vector tmp_vec; Allocator &al; + LocationManager &lm; SymbolTable *current_scope; // The current_module contains the current module that is being visited; // this is used to append to the module dependencies if needed @@ -517,11 +532,11 @@ class CommonVisitor : public AST::BaseVisitor { std::set dependencies; bool allow_implicit_casting; - CommonVisitor(Allocator &al, SymbolTable *symbol_table, + CommonVisitor(Allocator &al, LocationManager &lm, SymbolTable *symbol_table, diag::Diagnostics &diagnostics, bool main_module, std::map &ast_overload, std::string parent_dir, std::string import_path, bool allow_implicit_casting_) - : diag{diagnostics}, al{al}, current_scope{symbol_table}, main_module{main_module}, + : diag{diagnostics}, al{al}, lm{lm}, current_scope{symbol_table}, main_module{main_module}, ast_overload{ast_overload}, parent_dir{parent_dir}, import_path{import_path}, current_body{nullptr}, ann_assign_target_type{nullptr}, allow_implicit_casting{allow_implicit_casting_} { @@ -549,7 +564,7 @@ class CommonVisitor : public AST::BaseVisitor { std::vector paths = {rl_path, parent_dir}; bool ltypes, enum_py; ASR::Module_t *m = load_module(al, tu_symtab, module_name, - loc, true, paths, + loc, diag, lm, true, paths, ltypes, enum_py, [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); }, allow_implicit_casting); @@ -3118,11 +3133,11 @@ class SymbolTableVisitor : public CommonVisitor { std::map> overload_defs; - SymbolTableVisitor(Allocator &al, SymbolTable *symbol_table, + SymbolTableVisitor(Allocator &al, LocationManager &lm, SymbolTable *symbol_table, diag::Diagnostics &diagnostics, bool main_module, std::map &ast_overload, std::string parent_dir, std::string import_path, bool allow_implicit_casting_) - : CommonVisitor(al, symbol_table, diagnostics, main_module, ast_overload, + : CommonVisitor(al, lm, symbol_table, diagnostics, main_module, ast_overload, parent_dir, import_path, allow_implicit_casting_), is_derived_type{false} {} @@ -3470,7 +3485,7 @@ class SymbolTableVisitor : public CommonVisitor { bool ltypes, enum_py; set_module_symbol(msym, paths); t = (ASR::symbol_t*)(load_module(al, st, - msym, x.base.base.loc, false, paths, ltypes, enum_py, + msym, x.base.base.loc, diag, lm, false, paths, ltypes, enum_py, [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); }, allow_implicit_casting)); if (ltypes || enum_py) { @@ -3516,7 +3531,7 @@ class SymbolTableVisitor : public CommonVisitor { bool ltypes, enum_py; set_module_symbol(mod_sym, paths); t = (ASR::symbol_t*)(load_module(al, st, - mod_sym, x.base.base.loc, false, paths, ltypes, enum_py, + mod_sym, x.base.base.loc, diag, lm, false, paths, ltypes, enum_py, [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); }, allow_implicit_casting)); if (ltypes || enum_py) { @@ -3617,12 +3632,12 @@ class SymbolTableVisitor : public CommonVisitor { } }; -Result symbol_table_visitor(Allocator &al, const AST::Module_t &ast, +Result symbol_table_visitor(Allocator &al, LocationManager &lm, const AST::Module_t &ast, diag::Diagnostics &diagnostics, bool main_module, std::map &ast_overload, std::string parent_dir, std::string import_path, bool allow_implicit_casting) { - SymbolTableVisitor v(al, nullptr, diagnostics, main_module, ast_overload, + SymbolTableVisitor v(al, lm, nullptr, diagnostics, main_module, ast_overload, parent_dir, import_path, allow_implicit_casting); try { v.visit_Module(ast); @@ -3647,10 +3662,10 @@ class BodyVisitor : public CommonVisitor { int64_t gotoids; - BodyVisitor(Allocator &al, ASR::asr_t *unit, diag::Diagnostics &diagnostics, + BodyVisitor(Allocator &al, LocationManager &lm, ASR::asr_t *unit, diag::Diagnostics &diagnostics, bool main_module, std::map &ast_overload, bool allow_implicit_casting_) - : CommonVisitor(al, nullptr, diagnostics, main_module, ast_overload, "", "", allow_implicit_casting_), + : CommonVisitor(al, lm, nullptr, diagnostics, main_module, ast_overload, "", "", allow_implicit_casting_), asr{unit}, gotoids{0} {} @@ -5753,14 +5768,14 @@ class BodyVisitor : public CommonVisitor { } }; -Result body_visitor(Allocator &al, +Result body_visitor(Allocator &al, LocationManager &lm, const AST::Module_t &ast, diag::Diagnostics &diagnostics, ASR::asr_t *unit, bool main_module, std::map &ast_overload, bool allow_implicit_casting) { - BodyVisitor b(al, unit, diagnostics, main_module, ast_overload, allow_implicit_casting); + BodyVisitor b(al, lm, unit, diagnostics, main_module, ast_overload, allow_implicit_casting); try { b.visit_Module(ast); } catch (const SemanticError &e) { @@ -5815,7 +5830,7 @@ std::string get_parent_dir(const std::string &path) { return path.substr(0,idx); } -Result python_ast_to_asr(Allocator &al, +Result python_ast_to_asr(Allocator &al, LocationManager &lm, AST::ast_t &ast, diag::Diagnostics &diagnostics, CompilerOptions &compiler_options, bool main_module, std::string file_path, bool allow_implicit_casting) { @@ -5824,7 +5839,7 @@ Result python_ast_to_asr(Allocator &al, AST::Module_t *ast_m = AST::down_cast2(&ast); ASR::asr_t *unit; - auto res = symbol_table_visitor(al, *ast_m, diagnostics, main_module, + auto res = symbol_table_visitor(al, lm, *ast_m, diagnostics, main_module, ast_overload, parent_dir, compiler_options.import_path, allow_implicit_casting); if (res.ok) { unit = res.result; @@ -5835,7 +5850,7 @@ Result python_ast_to_asr(Allocator &al, LFORTRAN_ASSERT(asr_verify(*tu, true, diagnostics)); if (!compiler_options.symtab_only) { - auto res2 = body_visitor(al, *ast_m, diagnostics, unit, main_module, + auto res2 = body_visitor(al, lm, *ast_m, diagnostics, unit, main_module, ast_overload, allow_implicit_casting); if (res2.ok) { tu = res2.result; diff --git a/src/lpython/semantics/python_ast_to_asr.h b/src/lpython/semantics/python_ast_to_asr.h index 72f18ac1db..eb8869b9a7 100644 --- a/src/lpython/semantics/python_ast_to_asr.h +++ b/src/lpython/semantics/python_ast_to_asr.h @@ -8,7 +8,7 @@ namespace LFortran::LPython { std::string pickle_python(AST::ast_t &ast, bool colors=false, bool indent=false); std::string pickle_tree_python(AST::ast_t &ast, bool colors=true); - Result python_ast_to_asr(Allocator &al, + Result python_ast_to_asr(Allocator &al, LocationManager &lm, LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, CompilerOptions &compiler_options, bool main_module, std::string file_path, bool allow_implicit_casting=false); diff --git a/src/lpython/tests/test_error_rendering.cpp b/src/lpython/tests/test_error_rendering.cpp index 4fd2af3b95..1c867a5a61 100644 --- a/src/lpython/tests/test_error_rendering.cpp +++ b/src/lpython/tests/test_error_rendering.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include @@ -62,12 +62,19 @@ TEST_CASE("Error Render: primary/secondary labels, single line") { Location loc1, loc2, loc3; LocationManager lm; input = "One line text\n"; - lm.in_filename = "input"; - lm.get_newlines(input, lm.in_newlines); - lm.out_start.push_back(0); - lm.in_start.push_back(0); - lm.in_start.push_back(input.size()); - lm.out_start.push_back(input.size()); + { + std::ofstream out("input.txt"); + out << input; + LocationManager::FileLocations fl; + fl.in_filename = "input.txt"; + lm.get_newlines(input, fl.in_newlines); + fl.out_start.push_back(0); + fl.in_start.push_back(0); + fl.in_start.push_back(input.size()); + fl.out_start.push_back(input.size()); + lm.files.push_back(fl); + lm.file_ends.push_back(input.size()); + } loc1.first = 4; loc1.last = 7; @@ -83,10 +90,10 @@ TEST_CASE("Error Render: primary/secondary labels, single line") { Label("", {loc1}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with label no message - --> input:1:5 + --> input.txt:1:5 | 1 | One line text | ^^^^ @@ -101,10 +108,10 @@ semantic error: Error with label no message Label("label message", {loc1, loc2}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with label and message - --> input:1:5 + --> input.txt:1:5 | 1 | One line text | ^^^^ ^^^^ label message @@ -118,10 +125,10 @@ semantic error: Error with label and message Label("label message", {loc1, loc2, loc3}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with label and message - --> input:1:5 + --> input.txt:1:5 | 1 | One line text | ^^^^ ^^^^ label message @@ -139,10 +146,10 @@ semantic error: Error with label and message Label("label2 message", {loc2}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with two labels and message - --> input:1:5 + --> input.txt:1:5 | 1 | One line text | ^^^^ label1 message @@ -161,10 +168,10 @@ semantic error: Error with two labels and message Label("label3 message", {loc3}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with two labels and message - --> input:1:5 + --> input.txt:1:5 | 1 | One line text | ^^^^ label1 message @@ -186,10 +193,10 @@ semantic error: Error with two labels and message Label("label3 secondary message", {loc3}, false) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with two labels and message - --> input:1:5 + --> input.txt:1:5 | 1 | One line text | ^^^^ label1 primary message @@ -211,10 +218,10 @@ semantic error: Error with two labels and message Label("label3 secondary message", {loc3}, false) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with three labels and message, two spans - --> input:1:5 + --> input.txt:1:5 | 1 | One line text | ~~~~ ~~~~ label1 secondary message @@ -233,13 +240,19 @@ TEST_CASE("Error Render: primary/secondary labels, multi line") { Location loc1, loc2, loc3; LocationManager lm; input = "One line text\nSecond line text\nThird line text\n"; - lm.in_filename = "input"; - lm.get_newlines(input, lm.in_newlines); - lm.out_start.push_back(0); - lm.in_start.push_back(0); - lm.in_start.push_back(input.size()); - lm.out_start.push_back(input.size()); - + { + std::ofstream out("input.txt"); + out << input; + LocationManager::FileLocations fl; + fl.in_filename = "input.txt"; + lm.get_newlines(input, fl.in_newlines); + fl.out_start.push_back(0); + fl.in_start.push_back(0); + fl.in_start.push_back(input.size()); + fl.out_start.push_back(input.size()); + lm.files.push_back(fl); + lm.file_ends.push_back(input.size()); + } loc1.first = 4; // 1 line loc1.last = 24; // 2 line loc2.first = 9; // 1 text @@ -254,10 +267,10 @@ TEST_CASE("Error Render: primary/secondary labels, multi line") { Label("Multilines", {loc1}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with label no message - --> input:1:5 - 2:11 + --> input.txt:1:5 - 2:11 | 1 | One line text | ^^^^^^^^^... @@ -275,10 +288,10 @@ semantic error: Error with label no message Label("Two spans", {loc1, loc2}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with label, two spans - --> input:1:5 - 2:11 + --> input.txt:1:5 - 2:11 | 1 | One line text | ^^^^^^^^^... @@ -303,10 +316,10 @@ semantic error: Error with label, two spans Label("Two spans", {loc3, loc2}) } ); - out = render_diagnostic_human(d, input, lm, false, false); + out = render_diagnostic_human(d, lm, false, false); ref = S(R"""( semantic error: Error with label, two spans - --> input:1:1 + --> input.txt:1:1 | 1 | One line text | ^^^ Two spans diff --git a/tests/errors/test_import/__init__.py b/tests/errors/test_import/__init__.py new file mode 100644 index 0000000000..6475f76620 --- /dev/null +++ b/tests/errors/test_import/__init__.py @@ -0,0 +1 @@ +from .test_import_1 import test diff --git a/tests/errors/test_import/test_import_1.py b/tests/errors/test_import/test_import_1.py new file mode 100644 index 0000000000..6d3f690656 --- /dev/null +++ b/tests/errors/test_import/test_import_1.py @@ -0,0 +1,4 @@ +from ltypes import Const, i32 + +def test(x: i32) -> i32: + return x ** 2 diff --git a/tests/errors/test_import/test_import_2.py b/tests/errors/test_import/test_import_2.py new file mode 100644 index 0000000000..cb4ca90016 --- /dev/null +++ b/tests/errors/test_import/test_import_2.py @@ -0,0 +1,3 @@ +from ltypes import Const, i32 + +X: Const[i32] = 1.23 diff --git a/tests/errors/test_import_01.py b/tests/errors/test_import_01.py new file mode 100644 index 0000000000..d3511831bd --- /dev/null +++ b/tests/errors/test_import_01.py @@ -0,0 +1,4 @@ +from ltypes import Const, f64 +from test_import import test + +X: Const[f64] = test(5.0) diff --git a/tests/errors/test_import_02.py b/tests/errors/test_import_02.py new file mode 100644 index 0000000000..271d558e52 --- /dev/null +++ b/tests/errors/test_import_02.py @@ -0,0 +1,3 @@ +from test_import.test_import_2 import X + +print(X) diff --git a/tests/reference/asr-test_import_01-b859c43.json b/tests/reference/asr-test_import_01-b859c43.json new file mode 100644 index 0000000000..a53896722b --- /dev/null +++ b/tests/reference/asr-test_import_01-b859c43.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-test_import_01-b859c43", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/test_import_01.py", + "infile_hash": "dcde95aa235a4257a7ee1b22b0d3fa4d9ba54209066e0a4688fd7722", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-test_import_01-b859c43.stderr", + "stderr_hash": "ef59d49c8273cdd97e830cac94b3cc620fb24b07ce00c3394081c9c5", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-test_import_01-b859c43.stderr b/tests/reference/asr-test_import_01-b859c43.stderr new file mode 100644 index 0000000000..a2a50d4911 --- /dev/null +++ b/tests/reference/asr-test_import_01-b859c43.stderr @@ -0,0 +1,10 @@ +semantic error: Type mismatch in procedure call; the types must be compatible + --> tests/errors/test_import_01.py:4:22 + | +4 | X: Const[f64] = test(5.0) + | ^^^ type mismatch (passed argument type is f64 but required type is i32) + + --> tests/errors/test_import/test_import_1.py:3:13 + | +3 | def test(x: i32) -> i32: + | ^^^ type mismatch (passed argument type is f64 but required type is i32) diff --git a/tests/reference/asr-test_import_02-55b47fa.json b/tests/reference/asr-test_import_02-55b47fa.json new file mode 100644 index 0000000000..4a11aa9cff --- /dev/null +++ b/tests/reference/asr-test_import_02-55b47fa.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-test_import_02-55b47fa", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/test_import_02.py", + "infile_hash": "a3326a7bd9f6acc935235e1c0ff9cf4c26eda5f4052af774a148856c", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-test_import_02-55b47fa.stderr", + "stderr_hash": "76231bde5dcf6b0c50fd898363a83aefd5dc79928d75da0feb346fba", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-test_import_02-55b47fa.stderr b/tests/reference/asr-test_import_02-55b47fa.stderr new file mode 100644 index 0000000000..298b0701d3 --- /dev/null +++ b/tests/reference/asr-test_import_02-55b47fa.stderr @@ -0,0 +1,11 @@ +warning: The module 'test_import/test_import_2' cannot be loaded + --> tests/errors/test_import_02.py:1:1 + | +1 | from test_import.test_import_2 import X + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ imported here + +semantic error: Type mismatch in annotation-assignment, the types must be compatible + --> tests/errors/test_import/test_import_2.py:3:1 + | +3 | X: Const[i32] = 1.23 + | ^ ^^^^ type mismatch ('i32' and 'f64') diff --git a/tests/tests.toml b/tests/tests.toml index 4bc6645fb3..2fe203e551 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -885,6 +885,14 @@ asr = true filename = "errors/test_for2.py" asr = true +[[test]] +filename = "errors/test_import_01.py" +asr = true + +[[test]] +filename = "errors/test_import_02.py" +asr = true + # tests/tokens/errors [[test]]