From 265386678ad434aa90d1d6cb5ce2717d928b8fc6 Mon Sep 17 00:00:00 2001 From: Vipul-Cariappa Date: Tue, 19 Mar 2024 18:50:15 +0530 Subject: [PATCH 1/9] Initial interactive shell implementation --- src/bin/lpython.cpp | 129 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 4 deletions(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 4a5da1a3d8..5ce6dd97fd 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -792,6 +793,123 @@ int emit_llvm(const std::string &infile, return 0; } +int interactive_python_repl( + LCompilers::PassManager& pass_manager, + CompilerOptions &compiler_options, + bool time_report) +{ + Allocator al(4*1024); + + LCompilers::diag::Diagnostics diagnostics; + LCompilers::LocationManager lm; + std::vector> times; + std::string infile; + + std::string code_string; + std::cout << ">>> "; + size_t cell_count = 0; + for (std::string input; std::getline(std::cin, input);) { + + if (input == "exit" || input == "quit") // exit condition + return 0; + + if ((input.rfind("def", 0) == 0) || + (input.rfind("for", 0) == 0) || + (input.rfind("if", 0) == 0) || + (input.rfind("else", 0) == 0) || + (input.rfind("elif", 0) == 0) || + (input.rfind("class", 0) == 0) || + (input.rfind(' ', 0) == 0) || + (input.rfind('\t', 0) == 0)) { + // start of a block + code_string += input + "\n"; + std::cout << "... "; + continue; + } + code_string += input + "\n"; + + // std::cout << "code block: \n" << code_string; + + { + cell_count++; + LCompilers::LocationManager::FileLocations fl; + infile = "stdin" + std::to_string(cell_count); + fl.in_filename = infile; + lm.files.push_back(fl); + lm.init_simple(code_string); + lm.file_ends.push_back(code_string.size()); + } + + /* parse and run */ + // parsing string to AST + auto parsing_start = std::chrono::high_resolution_clock::now(); + // ???: change `parse_python_file` to `parse` or `parse_string` + LCompilers::Result r = LCompilers::LPython::parse(al, code_string, 0, diagnostics); + 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(lm, compiler_options); + if (!r.ok) { + LCOMPILERS_ASSERT(diagnostics.has_error()) + print_time_report(times, time_report); + return 1; + } + + // AST -> ASR + LCompilers::LPython::AST::ast_t* ast = (LCompilers::LPython::AST::ast_t*)r.result; + diagnostics.diagnostics.clear(); + auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); + LCompilers::Result + r1 = LCompilers::LPython::python_ast_to_asr(al, lm, nullptr, *ast, diagnostics, compiler_options, + !(false && compiler_options.po.disable_main), "__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(lm, compiler_options); + if (!r1.ok) { + LCOMPILERS_ASSERT(diagnostics.has_error()) + print_time_report(times, time_report); + return 2; + } + LCompilers::ASR::TranslationUnit_t* asr = r1.result; + diagnostics.diagnostics.clear(); + + LCompilers::PythonCompiler fe(compiler_options); + LCompilers::LLVMEvaluator e(compiler_options.target); + std::unique_ptr m; + auto asr_to_llvm_start = std::chrono::high_resolution_clock::now(); + LCompilers::Result> + 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(lm, compiler_options); + if (!res.ok) { + LCOMPILERS_ASSERT(diagnostics.has_error()) + print_time_report(times, time_report); + return 3; + } + m = std::move(res.result); + + bool call_init = false; + bool call_stmts = false; + if (m->get_return_type("__module___main_____main__global_init") == "void") + call_init = true; + if (m->get_return_type("__module___main_____main__global_stmts") == "void") + call_stmts = true; + + e.add_module(std::move(m)); + if (call_init) + e.voidfn("__module___main_____main__global_init"); + if (call_stmts) + e.voidfn("__module___main_____main__global_stmts"); + /* end parse and run */ + + code_string = ""; + std::cout << ">>> "; + } + return 0; +} + /* Compiles python to object file, if `to_jit` is false otherwise execute python code using llvm JIT @@ -1778,6 +1896,9 @@ int main(int argc, char *argv[]) compiler_options.use_colors = !arg_no_color; compiler_options.indent = !arg_no_indent; + lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); + lpython_pass_manager.use_default_passes(); + // if (fmt) { // return format(arg_fmt_file, arg_fmt_inplace, !arg_fmt_no_color, // arg_fmt_indent, arg_fmt_indent_unit, compiler_options); @@ -1824,8 +1945,10 @@ int main(int argc, char *argv[]) } if (arg_files.size() == 0) { - std::cerr << "Interactive prompt is not implemented yet in LPython" << std::endl; - return 1; + compiler_options.po.disable_main = true; + compiler_options.emit_debug_line_column = false; + compiler_options.generate_object_code = false; + return interactive_python_repl(lpython_pass_manager, compiler_options, time_report); } // TODO: for now we ignore the other filenames, only handle @@ -1868,7 +1991,6 @@ int main(int argc, char *argv[]) // return emit_c_preprocessor(arg_file, compiler_options); // } - lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); if (show_tokens) { return emit_tokens(arg_file, true, compiler_options); } @@ -1910,7 +2032,6 @@ int main(int argc, char *argv[]) return 1; #endif } - lpython_pass_manager.use_default_passes(); if (show_llvm) { #ifdef HAVE_LFORTRAN_LLVM return emit_llvm(arg_file, runtime_library_dir, lpython_pass_manager, compiler_options); From 2360d8eaa1983ef5e0556d034de4dbe19083bb80 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Wed, 8 May 2024 19:13:53 +0530 Subject: [PATCH 2/9] remember global functions and variables declared --- .gitignore | 3 + src/bin/lpython.cpp | 166 +++++++------ src/lpython/parser/parser.cpp | 27 +++ src/lpython/parser/parser.h | 5 + src/lpython/python_evaluator.cpp | 199 +++++++++++++++- src/lpython/python_evaluator.h | 16 +- src/lpython/semantics/python_ast_to_asr.cpp | 251 +++++++++++++++++++- src/lpython/semantics/python_ast_to_asr.h | 2 +- 8 files changed, 579 insertions(+), 90 deletions(-) diff --git a/.gitignore b/.gitignore index 2e1546420b..873a23ee9e 100644 --- a/.gitignore +++ b/.gitignore @@ -234,3 +234,6 @@ integration_tests/array_02_decl integration_tests/array_02_decl.c integration_tests/expr_12 integration_tests/expr_12.c + +# Interactive Shell +/input diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 5ce6dd97fd..2805f659bb 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -794,22 +794,24 @@ int emit_llvm(const std::string &infile, } int interactive_python_repl( - LCompilers::PassManager& pass_manager, + // LCompilers::PassManager& pass_manager, CompilerOptions &compiler_options, - bool time_report) + bool /*time_report*/) { Allocator al(4*1024); - + compiler_options.interactive = true; + LCompilers::PythonCompiler fe(compiler_options); LCompilers::diag::Diagnostics diagnostics; - LCompilers::LocationManager lm; + LCompilers::LocationManager lm; std::vector> times; - std::string infile; - + LCompilers::PythonCompiler::EvalResult r; + LCompilers::PassManager pass_manager; + pass_manager.use_default_passes(); + std::string code_string; std::cout << ">>> "; size_t cell_count = 0; for (std::string input; std::getline(std::cin, input);) { - if (input == "exit" || input == "quit") // exit condition return 0; @@ -833,76 +835,100 @@ int interactive_python_repl( { cell_count++; LCompilers::LocationManager::FileLocations fl; - infile = "stdin" + std::to_string(cell_count); - fl.in_filename = infile; + fl.in_filename = "input"; + std::ofstream out("input"); + out << code_string; lm.files.push_back(fl); lm.init_simple(code_string); lm.file_ends.push_back(code_string.size()); } - /* parse and run */ - // parsing string to AST - auto parsing_start = std::chrono::high_resolution_clock::now(); - // ???: change `parse_python_file` to `parse` or `parse_string` - LCompilers::Result r = LCompilers::LPython::parse(al, code_string, 0, diagnostics); - 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(lm, compiler_options); - if (!r.ok) { - LCOMPILERS_ASSERT(diagnostics.has_error()) - print_time_report(times, time_report); - return 1; + try { + auto evaluation_start_time = std::chrono::high_resolution_clock::now(); + LCompilers::Result + res = fe.evaluate(code_string, false, lm, pass_manager, diagnostics); + std::cerr << diagnostics.render(lm, compiler_options); + if (res.ok) { + r = res.result; + } else { + LCOMPILERS_ASSERT(diagnostics.has_error()) + code_string = ""; + std::cout << ">>> "; + continue; + } + + auto evaluation_end_time = std::chrono::high_resolution_clock::now(); + times.push_back(std::make_pair("evalution " + std::to_string(cell_count), std::chrono::duration + (evaluation_start_time - evaluation_end_time).count())); + + } catch (const LCompilers::LCompilersException &e) { + std::cerr << "Internal Compiler Error: Unhandled exception" << std::endl; + std::vector d = e.stacktrace_addresses(); + get_local_addresses(d); + get_local_info(d); + std::cerr << stacktrace2str(d, LCompilers::stacktrace_depth); + std::cerr << e.name() + ": " << e.msg() << std::endl; + + code_string = ""; + std::cout << ">>> "; + continue; } - // AST -> ASR - LCompilers::LPython::AST::ast_t* ast = (LCompilers::LPython::AST::ast_t*)r.result; - diagnostics.diagnostics.clear(); - auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); - LCompilers::Result - r1 = LCompilers::LPython::python_ast_to_asr(al, lm, nullptr, *ast, diagnostics, compiler_options, - !(false && compiler_options.po.disable_main), "__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(lm, compiler_options); - if (!r1.ok) { - LCOMPILERS_ASSERT(diagnostics.has_error()) - print_time_report(times, time_report); - return 2; - } - LCompilers::ASR::TranslationUnit_t* asr = r1.result; - diagnostics.diagnostics.clear(); - - LCompilers::PythonCompiler fe(compiler_options); - LCompilers::LLVMEvaluator e(compiler_options.target); - std::unique_ptr m; - auto asr_to_llvm_start = std::chrono::high_resolution_clock::now(); - LCompilers::Result> - 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(lm, compiler_options); - if (!res.ok) { - LCOMPILERS_ASSERT(diagnostics.has_error()) - print_time_report(times, time_report); - return 3; + switch (r.type) { + case (LCompilers::PythonCompiler::EvalResult::integer4) : { + // if (verbose) std::cout << "Return type: integer" << std::endl; + // if (verbose) section("Result:"); + std::cout << r.i32 << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::integer8) : { + // if (verbose) std::cout << "Return type: integer(8)" << std::endl; + // if (verbose) section("Result:"); + std::cout << r.i64 << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::real4) : { + // if (verbose) std::cout << "Return type: real" << std::endl; + // if (verbose) section("Result:"); + std::cout << std::setprecision(8) << r.f32 << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::real8) : { + // if (verbose) std::cout << "Return type: real(8)" << std::endl; + // if (verbose) section("Result:"); + std::cout << std::setprecision(17) << r.f64 << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::complex4) : { + // if (verbose) std::cout << "Return type: complex" << std::endl; + // if (verbose) section("Result:"); + std::cout << std::setprecision(8) << "(" << r.c32.re << ", " << r.c32.im << ")" << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::complex8) : { + // if (verbose) std::cout << "Return type: complex(8)" << std::endl; + // if (verbose) section("Result:"); + std::cout << std::setprecision(17) << "(" << r.c64.re << ", " << r.c64.im << ")" << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::statement) : { + // if (verbose) { + // std::cout << "Return type: none" << std::endl; + // section("Result:"); + // std::cout << "(statement)" << std::endl; + // } + break; + } + case (LCompilers::PythonCompiler::EvalResult::none) : { + // if (verbose) { + // std::cout << "Return type: none" << std::endl; + // section("Result:"); + // std::cout << "(nothing to execute)" << std::endl; + // } + break; + } + default : throw LCompilers::LCompilersException("Return type not supported"); } - m = std::move(res.result); - - bool call_init = false; - bool call_stmts = false; - if (m->get_return_type("__module___main_____main__global_init") == "void") - call_init = true; - if (m->get_return_type("__module___main_____main__global_stmts") == "void") - call_stmts = true; - - e.add_module(std::move(m)); - if (call_init) - e.voidfn("__module___main_____main__global_init"); - if (call_stmts) - e.voidfn("__module___main_____main__global_stmts"); - /* end parse and run */ code_string = ""; std::cout << ">>> "; @@ -1948,7 +1974,7 @@ int main(int argc, char *argv[]) compiler_options.po.disable_main = true; compiler_options.emit_debug_line_column = false; compiler_options.generate_object_code = false; - return interactive_python_repl(lpython_pass_manager, compiler_options, time_report); + return interactive_python_repl(compiler_options, time_report); } // TODO: for now we ignore the other filenames, only handle diff --git a/src/lpython/parser/parser.cpp b/src/lpython/parser/parser.cpp index 92ab5023a7..38b455d2ad 100644 --- a/src/lpython/parser/parser.cpp +++ b/src/lpython/parser/parser.cpp @@ -42,6 +42,33 @@ Result parse(Allocator &al, const std::string &s, p.result.p, p.result.size(), p.type_ignore.p, p.type_ignore.size()); } +Result parse_to_ast(Allocator &al, const std::string &s, + uint32_t prev_loc, diag::Diagnostics &diagnostics) +{ + Parser p(al, diagnostics); + try { + p.parse(s, prev_loc); + } catch (const parser_local::TokenizerError &e) { + Error error; + diagnostics.diagnostics.push_back(e.d); + return error; + } catch (const parser_local::ParserError &e) { + Error error; + diagnostics.diagnostics.push_back(e.d); + return error; + } + + Location l; + if (p.result.size() == 0) { + l.first=0; + l.last=0; + } else { + l.first=p.result[0]->base.loc.first; + l.last=p.result[p.result.size()-1]->base.loc.last; + } + return LPython::AST::make_Interactive_t(al, l, p.result.p, p.result.size()); +} + void Parser::parse(const std::string &input, uint32_t prev_loc) { inp = input; diff --git a/src/lpython/parser/parser.h b/src/lpython/parser/parser.h index e9f6b92cba..ba596ddb43 100644 --- a/src/lpython/parser/parser.h +++ b/src/lpython/parser/parser.h @@ -1,6 +1,7 @@ #ifndef LPYTHON_PARSER_PARSER_H #define LPYTHON_PARSER_PARSER_H +#include "lpython/python_ast.h" #include #include #include @@ -35,6 +36,10 @@ Result parse(Allocator &al, const std::string &s, uint32_t prev_loc, diag::Diagnostics &diagnostics); +Result parse_to_ast(Allocator &al, + 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, diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index 44075e0a84..94c7b6410c 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -1,10 +1,15 @@ +#include "libasr/asr_scopes.h" +#include "lpython/python_ast.h" #include -#include #include +#include #include #include #include +#include +#include +#include #ifdef HAVE_LFORTRAN_LLVM #include @@ -28,14 +33,196 @@ PythonCompiler::PythonCompiler(CompilerOptions compiler_options) e{std::make_unique()}, eval_count{0}, #endif - compiler_options{compiler_options} -// symbol_table{nullptr} + compiler_options{compiler_options}, + symbol_table{nullptr} { } PythonCompiler::~PythonCompiler() = default; +Result PythonCompiler::evaluate( +#ifdef HAVE_LFORTRAN_LLVM + const std::string &code_orig, bool /*verbose*/, LocationManager &lm, + LCompilers::PassManager& pass_manager, diag::Diagnostics &diagnostics +#else + const std::string &/*code_orig*/, bool /*verbose*/, + LocationManager &/*lm*/, LCompilers::PassManager& /*pass_manager*/, + diag::Diagnostics &/*diagnostics*/ +#endif + ) +{ +#ifdef HAVE_LFORTRAN_LLVM + EvalResult result; + result.type = EvalResult::none; + + // Src -> AST + Result res = get_ast2(code_orig, diagnostics); + LCompilers::LPython::AST::ast_t* ast; + if (res.ok) { + ast = res.result; + } else { + return res.error; + } + + // if (verbose) { + result.ast = LCompilers::LPython::pickle_python(*ast, true, true); + // } + + std::cout << result.ast << std::endl; + + // AST -> ASR + Result res2 = get_asr3(*ast, diagnostics, lm); + ASR::TranslationUnit_t* asr; + if (res2.ok) { + asr = res2.result; + } else { + LCOMPILERS_ASSERT(diagnostics.has_error()) + return res2.error; + } + + // if (verbose) { + result.asr = pickle(*asr, true, true, true); + // } + + std::cout << result.asr << std::endl; + + // ASR -> LLVM + Result> res3 = get_llvm3(*asr, + pass_manager, diagnostics, lm.files.back().in_filename); + std::unique_ptr m; + if (res3.ok) { + m = std::move(res3.result); + } else { + LCOMPILERS_ASSERT(diagnostics.has_error()) + return res3.error; + } + + // if (verbose) { + // result.llvm_ir = m->str(); + // } + + std::cout << m->str() << std::endl; + + bool call_init = false; + bool call_stmts = false; + std::string init_fn = "__module___main_____main____lpython_interactive_init_" + std::to_string(eval_count) + "__"; + std::string stmts_fn = "__module___main_____main____lpython_interactive_stmts_" + std::to_string(eval_count) + "__"; + if (m->get_return_type(init_fn) != "none") { + call_init = true; + } + if (m->get_return_type(stmts_fn) != "none") { + call_stmts = true; + } + + e->add_module(std::move(m)); + if (call_init) { + e->voidfn(init_fn); + } + if (call_stmts) { + e->voidfn(stmts_fn); + } + + // TODO: remove init_fn and stmts_fn from asr + if (call_init) { + ASR::down_cast(symbol_table->resolve_symbol("__main__"))->m_symtab + ->erase_symbol("__main____lpython_interactive_init_" + std::to_string(eval_count) + "__"); + } + if (call_stmts) { + ASR::down_cast(symbol_table->resolve_symbol("__main__"))->m_symtab + ->erase_symbol("__main____lpython_interactive_stmts_" + std::to_string(eval_count) + "__"); + } + + eval_count++; + + // std::string return_type = m->get_return_type(run_fn); + + // // LLVM -> Machine code -> Execution + // e->add_module(std::move(m)); + // if (return_type == "integer4") { + // int32_t r = e->int32fn(run_fn); + // result.type = EvalResult::integer4; + // result.i32 = r; + // } else if (return_type == "integer8") { + // int64_t r = e->int64fn(run_fn); + // result.type = EvalResult::integer8; + // result.i64 = r; + // } else if (return_type == "real4") { + // float r = e->floatfn(run_fn); + // result.type = EvalResult::real4; + // result.f32 = r; + // } else if (return_type == "real8") { + // double r = e->doublefn(run_fn); + // result.type = EvalResult::real8; + // result.f64 = r; + // } else if (return_type == "complex4") { + // std::complex r = e->complex4fn(run_fn); + // result.type = EvalResult::complex4; + // result.c32.re = r.real(); + // result.c32.im = r.imag(); + // } else if (return_type == "complex8") { + // std::complex r = e->complex8fn(run_fn); + // result.type = EvalResult::complex8; + // result.c64.re = r.real(); + // result.c64.im = r.imag(); + // } else if (return_type == "void") { + // e->voidfn(run_fn); + // result.type = EvalResult::statement; + // } else if (return_type == "none") { + // result.type = EvalResult::none; + // } else { + // throw LCompilersException("PythonCompiler::evaluate(): Return type not supported"); + // } + return result; +#else + throw LCompilersException("LLVM is not enabled"); +#endif +} + +Result PythonCompiler::get_ast2( + const std::string &code_orig, diag::Diagnostics &diagnostics) +{ + // Src -> AST + const std::string *code=&code_orig; + std::string tmp; + Result + res = LCompilers::LPython::parse_to_ast(al, *code, 0, diagnostics); + // Result + // res = LCompilers::LPython::parse(al, *code, 0, diagnostics); + if (res.ok) { + return (LCompilers::LPython::AST::ast_t*)res.result; + } else { + LCOMPILERS_ASSERT(diagnostics.has_error()) + return res.error; + } +} + +Result PythonCompiler::get_asr3( + LCompilers::LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, + LocationManager &lm) +{ + ASR::TranslationUnit_t* asr; + // AST -> ASR + // Remove the old execution function if it exists + if (symbol_table) { + if (symbol_table->get_symbol(run_fn) != nullptr) { + symbol_table->erase_symbol(run_fn); + } + symbol_table->mark_all_variables_external(al); + } + auto res = LCompilers::LPython::python_ast_to_asr(al, lm, symbol_table, ast, diagnostics, + compiler_options, true, "__main__", "", false, true); + if (res.ok) { + asr = res.result; + } else { + LCOMPILERS_ASSERT(diagnostics.has_error()) + return res.error; + } + if (!symbol_table) symbol_table = asr->m_symtab; + + return asr; +} + Result> PythonCompiler::get_llvm3( #ifdef HAVE_LFORTRAN_LLVM ASR::TranslationUnit_t &asr, LCompilers::PassManager& lpm, @@ -47,8 +234,8 @@ Result> PythonCompiler::get_llvm3( ) { #ifdef HAVE_LFORTRAN_LLVM - eval_count++; - run_fn = "__lfortran_evaluate_" + std::to_string(eval_count); + // eval_count++; + // run_fn = "__lfortran_evaluate_" + std::to_string(eval_count); if (compiler_options.emit_debug_info) { if (!compiler_options.emit_debug_line_column) { @@ -68,7 +255,7 @@ Result> PythonCompiler::get_llvm3( Result> res = asr_to_llvm(asr, diagnostics, e->get_context(), al, lpm, compiler_options, - run_fn, infile); + "", infile); // ??? What about run function if (res.ok) { m = std::move(res.result); } else { diff --git a/src/lpython/python_evaluator.h b/src/lpython/python_evaluator.h index b18b0aaf88..17a453d20e 100644 --- a/src/lpython/python_evaluator.h +++ b/src/lpython/python_evaluator.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,17 @@ class PythonCompiler std::string llvm_ir; }; + Result evaluate( + const std::string &code_orig, bool verbose, LocationManager &lm, + LCompilers::PassManager& pass_manager, diag::Diagnostics &diagnostics); + + Result get_ast2( + const std::string &code_orig, diag::Diagnostics &diagnostics); + + Result get_asr3( + LCompilers::LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, + LocationManager &lm); + Result> get_llvm3(ASR::TranslationUnit_t &asr, LCompilers::PassManager& lpm, diag::Diagnostics &diagnostics, const std::string &infile); @@ -59,10 +71,10 @@ class PythonCompiler Allocator al; #ifdef HAVE_LFORTRAN_LLVM std::unique_ptr e; - int eval_count; + size_t eval_count; #endif CompilerOptions compiler_options; -// SymbolTable *symbol_table; + SymbolTable *symbol_table; std::string run_fn; }; diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index b8492e07a0..3b72816da8 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4117,6 +4117,66 @@ class SymbolTableVisitor : public CommonVisitor { global_scope = nullptr; tmp = tmp0; } + + void visit_Interactive(const AST::Interactive_t &x) { + ASR::asr_t *tmp0 = nullptr; + if (current_scope) { + LCOMPILERS_ASSERT(current_scope->asr_owner); + tmp0 = current_scope->asr_owner; + } else { + current_scope = al.make_new(nullptr); + // Create the TU early, so that asr_owner is set, so that + // ASRUtils::get_tu_symtab() can be used, which has an assert + // for asr_owner. + tmp0 = ASR::make_TranslationUnit_t(al, x.base.base.loc, + current_scope, nullptr, 0); + } + LCOMPILERS_ASSERT(ASR::is_a(*tmp0) && + ASR::is_a(*ASR::down_cast(tmp0))); + global_scope = current_scope; + + // Every module goes into a Module_t + SymbolTable *parent_scope = current_scope; + if (parent_scope->get_scope().find(module_name) == parent_scope->get_scope().end()) { + ASR::Module_t* module_sym = nullptr; + current_scope = al.make_new(parent_scope); + ASR::asr_t *tmp1 = ASR::make_Module_t(al, x.base.base.loc, + /* a_symtab */ current_scope, + /* a_name */ s2c(al, module_name), + nullptr, + 0, + false, false); + module_sym = ASR::down_cast(ASR::down_cast(tmp1)); + parent_scope->add_symbol(module_name, ASR::down_cast(tmp1)); + current_module_dependencies.reserve(al, 1); + for (size_t i=0; im_dependencies = current_module_dependencies.p; + module_sym->n_dependencies = current_module_dependencies.size(); + if (!overload_defs.empty()) { + create_GenericProcedure(x.base.base.loc); + } + } else { + ASR::Module_t* module_sym = + ASR::down_cast(parent_scope->resolve_symbol(module_name)); + current_scope = module_sym->m_symtab; + LCOMPILERS_ASSERT(module_sym != nullptr); + for (size_t i=0; im_dependencies = current_module_dependencies.p; + module_sym->n_dependencies = current_module_dependencies.size(); + if (!overload_defs.empty()) { + create_GenericProcedure(x.base.base.loc); + } + } + + global_scope = nullptr; + tmp = tmp0; + } ASR::symbol_t* create_implicit_interface_function(Location &loc, ASR::FunctionType_t *func, std::string func_name) { SymbolTable *parent_scope = current_scope; @@ -4802,6 +4862,28 @@ Result symbol_table_visitor(Allocator &al, LocationManager &lm, return unit; } +Result symbol_table_visitor(Allocator &al, LocationManager &lm, + SymbolTable* symtab, const AST::Interactive_t &ast, + diag::Diagnostics &diagnostics, bool main_module, std::string module_name, + std::map &ast_overload, std::string parent_dir, + std::vector import_paths, bool allow_implicit_casting) +{ + SymbolTableVisitor v(al, lm, symtab, diagnostics, main_module, module_name, ast_overload, + parent_dir, import_paths, allow_implicit_casting); + try { + v.visit_Interactive(ast); + } catch (const SemanticError &e) { + Error error; + diagnostics.diagnostics.push_back(e.d); + return error; + } catch (const SemanticAbort &) { + Error error; + return error; + } + ASR::asr_t *unit = v.tmp; + return unit; +} + class BodyVisitor : public CommonVisitor { private: @@ -4926,6 +5008,100 @@ class BodyVisitor : public CommonVisitor { tmp = asr; } + + void visit_Interactive(const AST::Interactive_t &x) { + static size_t interactive_execution_count = 0; + + ASR::TranslationUnit_t *unit = ASR::down_cast2(asr); + current_scope = unit->m_symtab; + LCOMPILERS_ASSERT(current_scope != nullptr); + ASR::symbol_t* module_sym = nullptr; + ASR::Module_t* mod = nullptr; + + LCOMPILERS_ASSERT(module_name.size() > 0); + module_sym = current_scope->get_symbol(module_name); + mod = ASR::down_cast(module_sym); + LCOMPILERS_ASSERT(mod != nullptr); + current_scope = mod->m_symtab; + LCOMPILERS_ASSERT(current_scope != nullptr); + + Vec items; + items.reserve(al, 4); + current_module_dependencies.reserve(al, 1); + for (size_t i=0; in_dependencies; i++ ) { + current_module_dependencies.push_back(al, mod->m_dependencies[i]); + } + mod->m_dependencies = current_module_dependencies.p; + mod->n_dependencies = current_module_dependencies.n; + + if (global_init.n > 0) { + // unit->m_items is used and set to nullptr in the + // `pass_wrap_global_stmts_into_function` pass + unit->m_items = global_init.p; + unit->n_items = global_init.size(); + std::string func_name = module_name + "__lpython_interactive_init_" + std::to_string(interactive_execution_count) + "__"; + LCompilers::PassOptions pass_options; + pass_options.run_fun = func_name; + pass_wrap_global_stmts(al, *unit, pass_options); + + ASR::symbol_t *f_sym = unit->m_symtab->get_symbol(func_name); + if (f_sym) { + // Add the `global_initilaizer` function into the + // module and later call this function to initialize the + // global variables like list, ... + ASR::Function_t *f = ASR::down_cast(f_sym); + f->m_symtab->parent = mod->m_symtab; + mod->m_symtab->add_symbol(func_name, (ASR::symbol_t *) f); + // Erase the function in TranslationUnit + unit->m_symtab->erase_symbol(func_name); + } + global_init.p = nullptr; + global_init.n = 0; + } + + if (items.n > 0) { + unit->m_items = items.p; + unit->n_items = items.size(); + std::string func_name = module_name + "__lpython_interactive_stmts_" + std::to_string(interactive_execution_count) + "__";; + // Wrap all the global statements into a Function + LCompilers::PassOptions pass_options; + pass_options.run_fun = func_name; + pass_wrap_global_stmts(al, *unit, pass_options); + + ASR::symbol_t *f_sym = unit->m_symtab->get_symbol(func_name); + if (f_sym) { + // Add the `global_statements` function into the + // module and later call this function to execute the + // global_statements + ASR::Function_t *f = ASR::down_cast(f_sym); + f->m_symtab->parent = mod->m_symtab; + mod->m_symtab->add_symbol(func_name, (ASR::symbol_t *) f); + // Erase the function in TranslationUnit + unit->m_symtab->erase_symbol(func_name); + } + items.p = nullptr; + items.n = 0; + } + + interactive_execution_count++; + + tmp = asr; + } void handle_fn(const AST::FunctionDef_t &x, ASR::Function_t &v) { current_scope = v.m_symtab; @@ -8318,7 +8494,31 @@ Result body_visitor(Allocator &al, LocationManager &lm, return tu; } +Result body_visitor(Allocator &al, LocationManager &lm, const AST::Interactive_t &ast, + diag::Diagnostics &diagnostics, + ASR::asr_t *unit, bool main_module, std::string module_name, + std::map &ast_overload, + bool allow_implicit_casting) +{ + BodyVisitor b(al, lm, unit, diagnostics, main_module, module_name, ast_overload, allow_implicit_casting); + try { + b.visit_Interactive(ast); + } catch (const SemanticError &e) { + Error error; + diagnostics.diagnostics.push_back(e.d); + return error; + } catch (const SemanticAbort &) { + Error error; + return error; + } + ASR::TranslationUnit_t *tu = ASR::down_cast2(unit); + return tu; +} + std::string get_parent_dir(const std::string &path) { + if (path == "") { + return std::filesystem::current_path().string(); + } int idx = path.size()-1; while (idx >= 0 && path[idx] != '/' && path[idx] != '\\') idx--; if (idx == -1) { @@ -8329,20 +8529,38 @@ std::string get_parent_dir(const std::string &path) { Result python_ast_to_asr(Allocator &al, LocationManager &lm, SymbolTable* symtab, AST::ast_t &ast, diag::Diagnostics &diagnostics, CompilerOptions &compiler_options, - bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting) + bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting, bool is_interactive) { std::map ast_overload; std::string parent_dir = get_parent_dir(file_path); - AST::Module_t *ast_m = AST::down_cast2(&ast); ASR::asr_t *unit; - auto res = symbol_table_visitor(al, lm, symtab, *ast_m, diagnostics, main_module, module_name, + AST::Module_t *ast_m = nullptr; + AST::Interactive_t *ast_i = nullptr; + + if (!is_interactive) { + ast_m = AST::down_cast2(&ast); + Result res = symbol_table_visitor(al, lm, symtab, *ast_m, diagnostics, main_module, module_name, ast_overload, parent_dir, compiler_options.import_paths, allow_implicit_casting); - if (res.ok) { - unit = res.result; + if (res.ok) { + unit = res.result; + } else { + return res.error; + } } else { - return res.error; + ast_i = AST::down_cast2(&ast); + if (!symtab) { + // Create new empty symbol table, as a module + } + Result res = symbol_table_visitor(al, lm, symtab, *ast_i, diagnostics, main_module, module_name, + ast_overload, parent_dir, compiler_options.import_paths, allow_implicit_casting); + if (res.ok) { + unit = res.result; + } else { + return res.error; + } } + ASR::TranslationUnit_t *tu = ASR::down_cast2(unit); if (compiler_options.po.dump_all_passes) { std::ofstream outfile ("pass_00_initial_asr_01.clj"); @@ -8367,12 +8585,23 @@ Result python_ast_to_asr(Allocator &al, LocationManager #endif if (!compiler_options.symtab_only) { - auto res2 = body_visitor(al, lm, *ast_m, diagnostics, unit, main_module, module_name, - ast_overload, allow_implicit_casting); - if (res2.ok) { - tu = res2.result; + if (!is_interactive) { + auto res2 = body_visitor(al, lm, *ast_m, diagnostics, unit, main_module, module_name, + ast_overload, allow_implicit_casting); + if (res2.ok) { + tu = res2.result; + } else { + return res2.error; + } } else { - return res2.error; + LCOMPILERS_ASSERT(ast_i != nullptr); + auto res2 = body_visitor(al, lm, *ast_i, diagnostics, unit, main_module, module_name, + ast_overload, allow_implicit_casting); + if (res2.ok) { + tu = res2.result; + } else { + return res2.error; + } } if (compiler_options.po.dump_all_passes) { std::ofstream outfile ("pass_00_initial_asr_02.clj"); diff --git a/src/lpython/semantics/python_ast_to_asr.h b/src/lpython/semantics/python_ast_to_asr.h index 8270846c32..ec05cdc4ca 100644 --- a/src/lpython/semantics/python_ast_to_asr.h +++ b/src/lpython/semantics/python_ast_to_asr.h @@ -8,7 +8,7 @@ namespace LCompilers::LPython { Result python_ast_to_asr(Allocator &al, LocationManager &lm, SymbolTable* symtab, LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, CompilerOptions &compiler_options, - bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting=false); + bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting=false, bool is_interactive=false); int save_pyc_files(const ASR::TranslationUnit_t &u, std::string infile); From c05976759fc35befa433189f3d99114632dab2ff Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Wed, 8 May 2024 19:17:54 +0530 Subject: [PATCH 3/9] avoid printing AST, ASR and LLVM IR --- src/lpython/python_evaluator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index 94c7b6410c..fed0527eab 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -66,10 +66,10 @@ Result PythonCompiler::evaluate( } // if (verbose) { - result.ast = LCompilers::LPython::pickle_python(*ast, true, true); + // result.ast = LCompilers::LPython::pickle_python(*ast, true, true); // } - std::cout << result.ast << std::endl; + // std::cout << result.ast << std::endl; // AST -> ASR Result res2 = get_asr3(*ast, diagnostics, lm); @@ -82,10 +82,10 @@ Result PythonCompiler::evaluate( } // if (verbose) { - result.asr = pickle(*asr, true, true, true); + // result.asr = pickle(*asr, true, true, true); // } - std::cout << result.asr << std::endl; + // std::cout << result.asr << std::endl; // ASR -> LLVM Result> res3 = get_llvm3(*asr, @@ -102,7 +102,7 @@ Result PythonCompiler::evaluate( // result.llvm_ir = m->str(); // } - std::cout << m->str() << std::endl; + // std::cout << m->str() << std::endl; bool call_init = false; bool call_stmts = false; From 54685d3e2b2ad195af983b3d8fd0f74a1cd60284 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Wed, 8 May 2024 19:35:36 +0530 Subject: [PATCH 4/9] fixed bug where error from previous cell is printed --- src/bin/lpython.cpp | 3 ++- src/libasr/diagnostics.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 2805f659bb..0bf54ce27f 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -847,11 +847,12 @@ int interactive_python_repl( auto evaluation_start_time = std::chrono::high_resolution_clock::now(); LCompilers::Result res = fe.evaluate(code_string, false, lm, pass_manager, diagnostics); - std::cerr << diagnostics.render(lm, compiler_options); if (res.ok) { r = res.result; } else { LCOMPILERS_ASSERT(diagnostics.has_error()) + std::cerr << diagnostics.render(lm, compiler_options); + diagnostics.clear(); code_string = ""; std::cout << ">>> "; continue; diff --git a/src/libasr/diagnostics.h b/src/libasr/diagnostics.h index 63e1d832c3..002e66216f 100644 --- a/src/libasr/diagnostics.h +++ b/src/libasr/diagnostics.h @@ -127,6 +127,10 @@ struct Diagnostics { diagnostics.push_back(d); } + void clear() { + diagnostics.clear(); + } + void message_label(const std::string &message, const std::vector &locations, const std::string &error_label, From d2f942cdf741e5ea4960b48c43ceea8d909c1b87 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Fri, 10 May 2024 07:58:24 +0530 Subject: [PATCH 5/9] detect decorators as incomplete input --- src/bin/lpython.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 0bf54ce27f..ae3d21bee1 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -821,6 +821,7 @@ int interactive_python_repl( (input.rfind("else", 0) == 0) || (input.rfind("elif", 0) == 0) || (input.rfind("class", 0) == 0) || + (input.rfind('@', 0) == 0) || (input.rfind(' ', 0) == 0) || (input.rfind('\t', 0) == 0)) { // start of a block From a54198acf49d6677aad33982b0aec2c10e7537cd Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Fri, 10 May 2024 09:04:35 +0530 Subject: [PATCH 6/9] clean up --- src/bin/lpython.cpp | 70 ++++++++++--------- src/lpython/python_evaluator.cpp | 75 +++------------------ src/lpython/semantics/python_ast_to_asr.cpp | 10 +-- 3 files changed, 53 insertions(+), 102 deletions(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index ae3d21bee1..94db405db6 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -744,6 +744,11 @@ void print_time_report(std::vector> ×, bool #ifdef HAVE_LFORTRAN_LLVM +void section(const std::string &s) +{ + std::cout << color(LCompilers::style::bold) << color(LCompilers::fg::blue) << s << color(LCompilers::style::reset) << color(LCompilers::fg::reset) << std::endl; +} + int emit_llvm(const std::string &infile, const std::string &runtime_library_dir, LCompilers::PassManager& pass_manager, @@ -794,9 +799,9 @@ int emit_llvm(const std::string &infile, } int interactive_python_repl( - // LCompilers::PassManager& pass_manager, + LCompilers::PassManager& pass_manager, CompilerOptions &compiler_options, - bool /*time_report*/) + bool verbose) { Allocator al(4*1024); compiler_options.interactive = true; @@ -805,8 +810,6 @@ int interactive_python_repl( LCompilers::LocationManager lm; std::vector> times; LCompilers::PythonCompiler::EvalResult r; - LCompilers::PassManager pass_manager; - pass_manager.use_default_passes(); std::string code_string; std::cout << ">>> "; @@ -831,8 +834,6 @@ int interactive_python_repl( } code_string += input + "\n"; - // std::cout << "code block: \n" << code_string; - { cell_count++; LCompilers::LocationManager::FileLocations fl; @@ -847,7 +848,7 @@ int interactive_python_repl( try { auto evaluation_start_time = std::chrono::high_resolution_clock::now(); LCompilers::Result - res = fe.evaluate(code_string, false, lm, pass_manager, diagnostics); + res = fe.evaluate(code_string, verbose, lm, pass_manager, diagnostics); if (res.ok) { r = res.result; } else { @@ -876,57 +877,66 @@ int interactive_python_repl( continue; } + if (verbose) { + section("AST:"); + std::cout << r.ast << std::endl; + section("ASR:"); + std::cout << r.asr << std::endl; + section("LLVM IR:"); + std::cout << r.llvm_ir << std::endl; + } + switch (r.type) { case (LCompilers::PythonCompiler::EvalResult::integer4) : { - // if (verbose) std::cout << "Return type: integer" << std::endl; - // if (verbose) section("Result:"); + if (verbose) std::cout << "Return type: integer" << std::endl; + if (verbose) section("Result:"); std::cout << r.i32 << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::integer8) : { - // if (verbose) std::cout << "Return type: integer(8)" << std::endl; - // if (verbose) section("Result:"); + if (verbose) std::cout << "Return type: integer(8)" << std::endl; + if (verbose) section("Result:"); std::cout << r.i64 << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::real4) : { - // if (verbose) std::cout << "Return type: real" << std::endl; - // if (verbose) section("Result:"); + if (verbose) std::cout << "Return type: real" << std::endl; + if (verbose) section("Result:"); std::cout << std::setprecision(8) << r.f32 << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::real8) : { - // if (verbose) std::cout << "Return type: real(8)" << std::endl; - // if (verbose) section("Result:"); + if (verbose) std::cout << "Return type: real(8)" << std::endl; + if (verbose) section("Result:"); std::cout << std::setprecision(17) << r.f64 << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::complex4) : { - // if (verbose) std::cout << "Return type: complex" << std::endl; - // if (verbose) section("Result:"); + if (verbose) std::cout << "Return type: complex" << std::endl; + if (verbose) section("Result:"); std::cout << std::setprecision(8) << "(" << r.c32.re << ", " << r.c32.im << ")" << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::complex8) : { - // if (verbose) std::cout << "Return type: complex(8)" << std::endl; - // if (verbose) section("Result:"); + if (verbose) std::cout << "Return type: complex(8)" << std::endl; + if (verbose) section("Result:"); std::cout << std::setprecision(17) << "(" << r.c64.re << ", " << r.c64.im << ")" << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::statement) : { - // if (verbose) { - // std::cout << "Return type: none" << std::endl; - // section("Result:"); - // std::cout << "(statement)" << std::endl; - // } + if (verbose) { + std::cout << "Return type: none" << std::endl; + section("Result:"); + std::cout << "(statement)" << std::endl; + } break; } case (LCompilers::PythonCompiler::EvalResult::none) : { - // if (verbose) { - // std::cout << "Return type: none" << std::endl; - // section("Result:"); - // std::cout << "(nothing to execute)" << std::endl; - // } + if (verbose) { + std::cout << "Return type: none" << std::endl; + section("Result:"); + std::cout << "(nothing to execute)" << std::endl; + } break; } default : throw LCompilers::LCompilersException("Return type not supported"); @@ -1976,7 +1986,7 @@ int main(int argc, char *argv[]) compiler_options.po.disable_main = true; compiler_options.emit_debug_line_column = false; compiler_options.generate_object_code = false; - return interactive_python_repl(compiler_options, time_report); + return interactive_python_repl(lpython_pass_manager, compiler_options, arg_v); } // TODO: for now we ignore the other filenames, only handle diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index fed0527eab..de0c4391ba 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -43,7 +43,7 @@ PythonCompiler::~PythonCompiler() = default; Result PythonCompiler::evaluate( #ifdef HAVE_LFORTRAN_LLVM - const std::string &code_orig, bool /*verbose*/, LocationManager &lm, + const std::string &code_orig, bool verbose, LocationManager &lm, LCompilers::PassManager& pass_manager, diag::Diagnostics &diagnostics #else const std::string &/*code_orig*/, bool /*verbose*/, @@ -65,11 +65,9 @@ Result PythonCompiler::evaluate( return res.error; } - // if (verbose) { - // result.ast = LCompilers::LPython::pickle_python(*ast, true, true); - // } - - // std::cout << result.ast << std::endl; + if (verbose) { + result.ast = LCompilers::LPython::pickle_python(*ast, true, true); + } // AST -> ASR Result res2 = get_asr3(*ast, diagnostics, lm); @@ -81,11 +79,9 @@ Result PythonCompiler::evaluate( return res2.error; } - // if (verbose) { - // result.asr = pickle(*asr, true, true, true); - // } - - // std::cout << result.asr << std::endl; + if (verbose) { + result.asr = pickle(*asr, true, true, true); + } // ASR -> LLVM Result> res3 = get_llvm3(*asr, @@ -98,11 +94,9 @@ Result PythonCompiler::evaluate( return res3.error; } - // if (verbose) { - // result.llvm_ir = m->str(); - // } - - // std::cout << m->str() << std::endl; + if (verbose) { + result.llvm_ir = m->str(); + } bool call_init = false; bool call_stmts = false; @@ -123,7 +117,6 @@ Result PythonCompiler::evaluate( e->voidfn(stmts_fn); } - // TODO: remove init_fn and stmts_fn from asr if (call_init) { ASR::down_cast(symbol_table->resolve_symbol("__main__"))->m_symtab ->erase_symbol("__main____lpython_interactive_init_" + std::to_string(eval_count) + "__"); @@ -134,45 +127,6 @@ Result PythonCompiler::evaluate( } eval_count++; - - // std::string return_type = m->get_return_type(run_fn); - - // // LLVM -> Machine code -> Execution - // e->add_module(std::move(m)); - // if (return_type == "integer4") { - // int32_t r = e->int32fn(run_fn); - // result.type = EvalResult::integer4; - // result.i32 = r; - // } else if (return_type == "integer8") { - // int64_t r = e->int64fn(run_fn); - // result.type = EvalResult::integer8; - // result.i64 = r; - // } else if (return_type == "real4") { - // float r = e->floatfn(run_fn); - // result.type = EvalResult::real4; - // result.f32 = r; - // } else if (return_type == "real8") { - // double r = e->doublefn(run_fn); - // result.type = EvalResult::real8; - // result.f64 = r; - // } else if (return_type == "complex4") { - // std::complex r = e->complex4fn(run_fn); - // result.type = EvalResult::complex4; - // result.c32.re = r.real(); - // result.c32.im = r.imag(); - // } else if (return_type == "complex8") { - // std::complex r = e->complex8fn(run_fn); - // result.type = EvalResult::complex8; - // result.c64.re = r.real(); - // result.c64.im = r.imag(); - // } else if (return_type == "void") { - // e->voidfn(run_fn); - // result.type = EvalResult::statement; - // } else if (return_type == "none") { - // result.type = EvalResult::none; - // } else { - // throw LCompilersException("PythonCompiler::evaluate(): Return type not supported"); - // } return result; #else throw LCompilersException("LLVM is not enabled"); @@ -187,8 +141,6 @@ Result PythonCompiler::get_ast2( std::string tmp; Result res = LCompilers::LPython::parse_to_ast(al, *code, 0, diagnostics); - // Result - // res = LCompilers::LPython::parse(al, *code, 0, diagnostics); if (res.ok) { return (LCompilers::LPython::AST::ast_t*)res.result; } else { @@ -203,11 +155,7 @@ Result PythonCompiler::get_asr3( { ASR::TranslationUnit_t* asr; // AST -> ASR - // Remove the old execution function if it exists if (symbol_table) { - if (symbol_table->get_symbol(run_fn) != nullptr) { - symbol_table->erase_symbol(run_fn); - } symbol_table->mark_all_variables_external(al); } auto res = LCompilers::LPython::python_ast_to_asr(al, lm, symbol_table, ast, diagnostics, @@ -234,9 +182,6 @@ Result> PythonCompiler::get_llvm3( ) { #ifdef HAVE_LFORTRAN_LLVM - // eval_count++; - // run_fn = "__lfortran_evaluate_" + std::to_string(eval_count); - if (compiler_options.emit_debug_info) { if (!compiler_options.emit_debug_line_column) { diagnostics.add(LCompilers::diag::Diagnostic( diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 3b72816da8..c485e91acc 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4162,16 +4162,11 @@ class SymbolTableVisitor : public CommonVisitor { } else { ASR::Module_t* module_sym = ASR::down_cast(parent_scope->resolve_symbol(module_name)); - current_scope = module_sym->m_symtab; LCOMPILERS_ASSERT(module_sym != nullptr); + current_scope = module_sym->m_symtab; for (size_t i=0; im_dependencies = current_module_dependencies.p; - module_sym->n_dependencies = current_module_dependencies.size(); - if (!overload_defs.empty()) { - create_GenericProcedure(x.base.base.loc); - } } global_scope = nullptr; @@ -5010,7 +5005,8 @@ class BodyVisitor : public CommonVisitor { } void visit_Interactive(const AST::Interactive_t &x) { - static size_t interactive_execution_count = 0; + static size_t interactive_execution_count = 0; // ???: should this be a class member variable + // interactive_execution_count should be the same as eval_count in PythonCompiler ASR::TranslationUnit_t *unit = ASR::down_cast2(asr); current_scope = unit->m_symtab; From da5feda476af9a0fdd7684b3c1a9bbfa0c87975c Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sat, 11 May 2024 16:30:33 +0530 Subject: [PATCH 7/9] update according to code review suggestion --- src/bin/lpython.cpp | 25 ++++++++++++--------- src/lpython/semantics/python_ast_to_asr.cpp | 3 --- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 94db405db6..d0cebae496 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -810,19 +810,20 @@ int interactive_python_repl( LCompilers::LocationManager lm; std::vector> times; LCompilers::PythonCompiler::EvalResult r; - + std::string code_string; std::cout << ">>> "; size_t cell_count = 0; for (std::string input; std::getline(std::cin, input);) { - if (input == "exit" || input == "quit") // exit condition + if (input == "exit" || input == "quit") { return 0; + } - if ((input.rfind("def", 0) == 0) || - (input.rfind("for", 0) == 0) || - (input.rfind("if", 0) == 0) || - (input.rfind("else", 0) == 0) || - (input.rfind("elif", 0) == 0) || + if ((input.rfind("def", 0) == 0) || + (input.rfind("for", 0) == 0) || + (input.rfind("if", 0) == 0) || + (input.rfind("else", 0) == 0) || + (input.rfind("elif", 0) == 0) || (input.rfind("class", 0) == 0) || (input.rfind('@', 0) == 0) || (input.rfind(' ', 0) == 0) || @@ -859,11 +860,11 @@ int interactive_python_repl( std::cout << ">>> "; continue; } - + auto evaluation_end_time = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("evalution " + std::to_string(cell_count), std::chrono::duration (evaluation_start_time - evaluation_end_time).count())); - + } catch (const LCompilers::LCompilersException &e) { std::cerr << "Internal Compiler Error: Unhandled exception" << std::endl; std::vector d = e.stacktrace_addresses(); @@ -1934,8 +1935,6 @@ int main(int argc, char *argv[]) compiler_options.use_colors = !arg_no_color; compiler_options.indent = !arg_no_indent; - lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); - lpython_pass_manager.use_default_passes(); // if (fmt) { // return format(arg_fmt_file, arg_fmt_inplace, !arg_fmt_no_color, @@ -1983,6 +1982,8 @@ int main(int argc, char *argv[]) } if (arg_files.size() == 0) { + lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); + lpython_pass_manager.use_default_passes(); compiler_options.po.disable_main = true; compiler_options.emit_debug_line_column = false; compiler_options.generate_object_code = false; @@ -2029,6 +2030,7 @@ int main(int argc, char *argv[]) // return emit_c_preprocessor(arg_file, compiler_options); // } + lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); if (show_tokens) { return emit_tokens(arg_file, true, compiler_options); } @@ -2070,6 +2072,7 @@ int main(int argc, char *argv[]) return 1; #endif } + lpython_pass_manager.use_default_passes(); if (show_llvm) { #ifdef HAVE_LFORTRAN_LLVM return emit_llvm(arg_file, runtime_library_dir, lpython_pass_manager, compiler_options); diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index c485e91acc..2eb633a116 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -8545,9 +8545,6 @@ Result python_ast_to_asr(Allocator &al, LocationManager } } else { ast_i = AST::down_cast2(&ast); - if (!symtab) { - // Create new empty symbol table, as a module - } Result res = symbol_table_visitor(al, lm, symtab, *ast_i, diagnostics, main_module, module_name, ast_overload, parent_dir, compiler_options.import_paths, allow_implicit_casting); if (res.ok) { From a33fa282837cf995971af6bdfdd6021701c11947 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sat, 11 May 2024 17:21:00 +0530 Subject: [PATCH 8/9] removed Interactive_t related stuff by merging required changes into SymbolTable.visit_Module --- src/lpython/parser/parser.cpp | 27 --- src/lpython/parser/parser.h | 4 - src/lpython/python_evaluator.cpp | 48 ++-- src/lpython/python_evaluator.h | 2 +- src/lpython/semantics/python_ast_to_asr.cpp | 247 ++------------------ src/lpython/semantics/python_ast_to_asr.h | 2 +- 6 files changed, 42 insertions(+), 288 deletions(-) diff --git a/src/lpython/parser/parser.cpp b/src/lpython/parser/parser.cpp index 38b455d2ad..92ab5023a7 100644 --- a/src/lpython/parser/parser.cpp +++ b/src/lpython/parser/parser.cpp @@ -42,33 +42,6 @@ Result parse(Allocator &al, const std::string &s, p.result.p, p.result.size(), p.type_ignore.p, p.type_ignore.size()); } -Result parse_to_ast(Allocator &al, const std::string &s, - uint32_t prev_loc, diag::Diagnostics &diagnostics) -{ - Parser p(al, diagnostics); - try { - p.parse(s, prev_loc); - } catch (const parser_local::TokenizerError &e) { - Error error; - diagnostics.diagnostics.push_back(e.d); - return error; - } catch (const parser_local::ParserError &e) { - Error error; - diagnostics.diagnostics.push_back(e.d); - return error; - } - - Location l; - if (p.result.size() == 0) { - l.first=0; - l.last=0; - } else { - l.first=p.result[0]->base.loc.first; - l.last=p.result[p.result.size()-1]->base.loc.last; - } - return LPython::AST::make_Interactive_t(al, l, p.result.p, p.result.size()); -} - void Parser::parse(const std::string &input, uint32_t prev_loc) { inp = input; diff --git a/src/lpython/parser/parser.h b/src/lpython/parser/parser.h index ba596ddb43..2e1c18eda8 100644 --- a/src/lpython/parser/parser.h +++ b/src/lpython/parser/parser.h @@ -36,10 +36,6 @@ Result parse(Allocator &al, const std::string &s, uint32_t prev_loc, diag::Diagnostics &diagnostics); -Result parse_to_ast(Allocator &al, - 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, diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index de0c4391ba..d0894abe27 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -31,7 +31,7 @@ PythonCompiler::PythonCompiler(CompilerOptions compiler_options) al{1024*1024}, #ifdef HAVE_LFORTRAN_LLVM e{std::make_unique()}, - eval_count{0}, + eval_count{1}, #endif compiler_options{compiler_options}, symbol_table{nullptr} @@ -70,7 +70,7 @@ Result PythonCompiler::evaluate( } // AST -> ASR - Result res2 = get_asr3(*ast, diagnostics, lm); + Result res2 = get_asr3(*ast, diagnostics, lm, true); ASR::TranslationUnit_t* asr; if (res2.ok) { asr = res2.result; @@ -84,6 +84,11 @@ Result PythonCompiler::evaluate( } // ASR -> LLVM + std::string module_prefix = "__module___main___"; + std::string module_name = "__main__"; + std::string sym_name = module_name + "global_stmts_" + std::to_string(eval_count) + "__"; + run_fn = module_prefix + sym_name; + Result> res3 = get_llvm3(*asr, pass_manager, diagnostics, lm.files.back().in_filename); std::unique_ptr m; @@ -98,32 +103,19 @@ Result PythonCompiler::evaluate( result.llvm_ir = m->str(); } - bool call_init = false; - bool call_stmts = false; - std::string init_fn = "__module___main_____main____lpython_interactive_init_" + std::to_string(eval_count) + "__"; - std::string stmts_fn = "__module___main_____main____lpython_interactive_stmts_" + std::to_string(eval_count) + "__"; - if (m->get_return_type(init_fn) != "none") { - call_init = true; - } - if (m->get_return_type(stmts_fn) != "none") { - call_stmts = true; + bool call_run_fn = false; + if (m->get_return_type(run_fn) != "none") { + call_run_fn = true; } e->add_module(std::move(m)); - if (call_init) { - e->voidfn(init_fn); - } - if (call_stmts) { - e->voidfn(stmts_fn); + if (call_run_fn) { + e->voidfn(run_fn); } - if (call_init) { - ASR::down_cast(symbol_table->resolve_symbol("__main__"))->m_symtab - ->erase_symbol("__main____lpython_interactive_init_" + std::to_string(eval_count) + "__"); - } - if (call_stmts) { - ASR::down_cast(symbol_table->resolve_symbol("__main__"))->m_symtab - ->erase_symbol("__main____lpython_interactive_stmts_" + std::to_string(eval_count) + "__"); + if (call_run_fn) { + ASR::down_cast(symbol_table->resolve_symbol(module_name))->m_symtab + ->erase_symbol(sym_name); } eval_count++; @@ -139,8 +131,8 @@ Result PythonCompiler::get_ast2( // Src -> AST const std::string *code=&code_orig; std::string tmp; - Result - res = LCompilers::LPython::parse_to_ast(al, *code, 0, diagnostics); + Result + res = LCompilers::LPython::parse(al, *code, 0, diagnostics); if (res.ok) { return (LCompilers::LPython::AST::ast_t*)res.result; } else { @@ -151,7 +143,7 @@ Result PythonCompiler::get_ast2( Result PythonCompiler::get_asr3( LCompilers::LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, - LocationManager &lm) + LocationManager &lm, bool is_interactive) { ASR::TranslationUnit_t* asr; // AST -> ASR @@ -159,7 +151,7 @@ Result PythonCompiler::get_asr3( symbol_table->mark_all_variables_external(al); } auto res = LCompilers::LPython::python_ast_to_asr(al, lm, symbol_table, ast, diagnostics, - compiler_options, true, "__main__", "", false, true); + compiler_options, true, "__main__", "", false, is_interactive ? eval_count : 0); if (res.ok) { asr = res.result; } else { @@ -200,7 +192,7 @@ Result> PythonCompiler::get_llvm3( Result> res = asr_to_llvm(asr, diagnostics, e->get_context(), al, lpm, compiler_options, - "", infile); // ??? What about run function + run_fn, infile); if (res.ok) { m = std::move(res.result); } else { diff --git a/src/lpython/python_evaluator.h b/src/lpython/python_evaluator.h index 17a453d20e..8ec6f632cd 100644 --- a/src/lpython/python_evaluator.h +++ b/src/lpython/python_evaluator.h @@ -61,7 +61,7 @@ class PythonCompiler Result get_asr3( LCompilers::LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, - LocationManager &lm); + LocationManager &lm, bool is_interactive=false); Result> get_llvm3(ASR::TranslationUnit_t &asr, LCompilers::PassManager& lpm, diag::Diagnostics &diagnostics, diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 2eb633a116..1538901fe0 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4086,55 +4086,6 @@ class SymbolTableVisitor : public CommonVisitor { ASR::is_a(*ASR::down_cast(tmp0))); global_scope = current_scope; - ASR::Module_t* module_sym = nullptr; - // Every module goes into a Module_t - SymbolTable *parent_scope = current_scope; - current_scope = al.make_new(parent_scope); - - ASR::asr_t *tmp1 = ASR::make_Module_t(al, x.base.base.loc, - /* a_symtab */ current_scope, - /* a_name */ s2c(al, module_name), - nullptr, - 0, - false, false); - - if (parent_scope->get_scope().find(module_name) != parent_scope->get_scope().end()) { - throw SemanticError("Module '" + module_name + "' already defined", tmp1->loc); - } - module_sym = ASR::down_cast(ASR::down_cast(tmp1)); - parent_scope->add_symbol(module_name, ASR::down_cast(tmp1)); - current_module_dependencies.reserve(al, 1); - for (size_t i=0; im_dependencies = current_module_dependencies.p; - module_sym->n_dependencies = current_module_dependencies.size(); - if (!overload_defs.empty()) { - create_GenericProcedure(x.base.base.loc); - } - global_scope = nullptr; - tmp = tmp0; - } - - void visit_Interactive(const AST::Interactive_t &x) { - ASR::asr_t *tmp0 = nullptr; - if (current_scope) { - LCOMPILERS_ASSERT(current_scope->asr_owner); - tmp0 = current_scope->asr_owner; - } else { - current_scope = al.make_new(nullptr); - // Create the TU early, so that asr_owner is set, so that - // ASRUtils::get_tu_symtab() can be used, which has an assert - // for asr_owner. - tmp0 = ASR::make_TranslationUnit_t(al, x.base.base.loc, - current_scope, nullptr, 0); - } - LCOMPILERS_ASSERT(ASR::is_a(*tmp0) && - ASR::is_a(*ASR::down_cast(tmp0))); - global_scope = current_scope; - // Every module goes into a Module_t SymbolTable *parent_scope = current_scope; if (parent_scope->get_scope().find(module_name) == parent_scope->get_scope().end()) { @@ -4857,28 +4808,6 @@ Result symbol_table_visitor(Allocator &al, LocationManager &lm, return unit; } -Result symbol_table_visitor(Allocator &al, LocationManager &lm, - SymbolTable* symtab, const AST::Interactive_t &ast, - diag::Diagnostics &diagnostics, bool main_module, std::string module_name, - std::map &ast_overload, std::string parent_dir, - std::vector import_paths, bool allow_implicit_casting) -{ - SymbolTableVisitor v(al, lm, symtab, diagnostics, main_module, module_name, ast_overload, - parent_dir, import_paths, allow_implicit_casting); - try { - v.visit_Interactive(ast); - } catch (const SemanticError &e) { - Error error; - diagnostics.diagnostics.push_back(e.d); - return error; - } catch (const SemanticAbort &) { - Error error; - return error; - } - ASR::asr_t *unit = v.tmp; - return unit; -} - class BodyVisitor : public CommonVisitor { private: @@ -4886,12 +4815,13 @@ class BodyVisitor : public CommonVisitor { ASR::asr_t *asr; std::vector do_loop_variables; bool using_func_attr = false; + size_t eval_count; BodyVisitor(Allocator &al, LocationManager &lm, ASR::asr_t *unit, diag::Diagnostics &diagnostics, bool main_module, std::string module_name, std::map &ast_overload, - bool allow_implicit_casting_) + bool allow_implicit_casting_, size_t eval_count=0) : CommonVisitor(al, lm, nullptr, diagnostics, main_module, module_name, ast_overload, "", {}, allow_implicit_casting_), - asr{unit} + asr{unit}, eval_count{eval_count} {} // Transforms statements to a list of ASR statements @@ -4981,99 +4911,10 @@ class BodyVisitor : public CommonVisitor { unit->m_items = items.p; unit->n_items = items.size(); std::string func_name = module_name + "global_stmts"; - // Wrap all the global statements into a Function - LCompilers::PassOptions pass_options; - pass_options.run_fun = func_name; - pass_wrap_global_stmts(al, *unit, pass_options); - - ASR::symbol_t *f_sym = unit->m_symtab->get_symbol(func_name); - if (f_sym) { - // Add the `global_statements` function into the - // module and later call this function to execute the - // global_statements - ASR::Function_t *f = ASR::down_cast(f_sym); - f->m_symtab->parent = mod->m_symtab; - mod->m_symtab->add_symbol(func_name, (ASR::symbol_t *) f); - // Erase the function in TranslationUnit - unit->m_symtab->erase_symbol(func_name); - } - items.p = nullptr; - items.n = 0; - } - - tmp = asr; - } - - void visit_Interactive(const AST::Interactive_t &x) { - static size_t interactive_execution_count = 0; // ???: should this be a class member variable - // interactive_execution_count should be the same as eval_count in PythonCompiler - - ASR::TranslationUnit_t *unit = ASR::down_cast2(asr); - current_scope = unit->m_symtab; - LCOMPILERS_ASSERT(current_scope != nullptr); - ASR::symbol_t* module_sym = nullptr; - ASR::Module_t* mod = nullptr; - - LCOMPILERS_ASSERT(module_name.size() > 0); - module_sym = current_scope->get_symbol(module_name); - mod = ASR::down_cast(module_sym); - LCOMPILERS_ASSERT(mod != nullptr); - current_scope = mod->m_symtab; - LCOMPILERS_ASSERT(current_scope != nullptr); - - Vec items; - items.reserve(al, 4); - current_module_dependencies.reserve(al, 1); - for (size_t i=0; i 0) { + // In Interactive Shell. Update the func_name accordingly + func_name += "_" + std::to_string(eval_count) + "__"; } - } - - for( size_t i = 0; i < mod->n_dependencies; i++ ) { - current_module_dependencies.push_back(al, mod->m_dependencies[i]); - } - mod->m_dependencies = current_module_dependencies.p; - mod->n_dependencies = current_module_dependencies.n; - - if (global_init.n > 0) { - // unit->m_items is used and set to nullptr in the - // `pass_wrap_global_stmts_into_function` pass - unit->m_items = global_init.p; - unit->n_items = global_init.size(); - std::string func_name = module_name + "__lpython_interactive_init_" + std::to_string(interactive_execution_count) + "__"; - LCompilers::PassOptions pass_options; - pass_options.run_fun = func_name; - pass_wrap_global_stmts(al, *unit, pass_options); - - ASR::symbol_t *f_sym = unit->m_symtab->get_symbol(func_name); - if (f_sym) { - // Add the `global_initilaizer` function into the - // module and later call this function to initialize the - // global variables like list, ... - ASR::Function_t *f = ASR::down_cast(f_sym); - f->m_symtab->parent = mod->m_symtab; - mod->m_symtab->add_symbol(func_name, (ASR::symbol_t *) f); - // Erase the function in TranslationUnit - unit->m_symtab->erase_symbol(func_name); - } - global_init.p = nullptr; - global_init.n = 0; - } - - if (items.n > 0) { - unit->m_items = items.p; - unit->n_items = items.size(); - std::string func_name = module_name + "__lpython_interactive_stmts_" + std::to_string(interactive_execution_count) + "__";; // Wrap all the global statements into a Function LCompilers::PassOptions pass_options; pass_options.run_fun = func_name; @@ -5094,8 +4935,6 @@ class BodyVisitor : public CommonVisitor { items.n = 0; } - interactive_execution_count++; - tmp = asr; } @@ -8473,9 +8312,9 @@ Result body_visitor(Allocator &al, LocationManager &lm, diag::Diagnostics &diagnostics, ASR::asr_t *unit, bool main_module, std::string module_name, std::map &ast_overload, - bool allow_implicit_casting) + bool allow_implicit_casting, size_t eval_count) { - BodyVisitor b(al, lm, unit, diagnostics, main_module, module_name, ast_overload, allow_implicit_casting); + BodyVisitor b(al, lm, unit, diagnostics, main_module, module_name, ast_overload, allow_implicit_casting, eval_count); try { b.visit_Module(ast); } catch (const SemanticError &e) { @@ -8490,27 +8329,6 @@ Result body_visitor(Allocator &al, LocationManager &lm, return tu; } -Result body_visitor(Allocator &al, LocationManager &lm, const AST::Interactive_t &ast, - diag::Diagnostics &diagnostics, - ASR::asr_t *unit, bool main_module, std::string module_name, - std::map &ast_overload, - bool allow_implicit_casting) -{ - BodyVisitor b(al, lm, unit, diagnostics, main_module, module_name, ast_overload, allow_implicit_casting); - try { - b.visit_Interactive(ast); - } catch (const SemanticError &e) { - Error error; - diagnostics.diagnostics.push_back(e.d); - return error; - } catch (const SemanticAbort &) { - Error error; - return error; - } - ASR::TranslationUnit_t *tu = ASR::down_cast2(unit); - return tu; -} - std::string get_parent_dir(const std::string &path) { if (path == "") { return std::filesystem::current_path().string(); @@ -8525,33 +8343,19 @@ std::string get_parent_dir(const std::string &path) { Result python_ast_to_asr(Allocator &al, LocationManager &lm, SymbolTable* symtab, AST::ast_t &ast, diag::Diagnostics &diagnostics, CompilerOptions &compiler_options, - bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting, bool is_interactive) + bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting, size_t eval_count) { std::map ast_overload; std::string parent_dir = get_parent_dir(file_path); ASR::asr_t *unit; - AST::Module_t *ast_m = nullptr; - AST::Interactive_t *ast_i = nullptr; - - if (!is_interactive) { - ast_m = AST::down_cast2(&ast); - Result res = symbol_table_visitor(al, lm, symtab, *ast_m, diagnostics, main_module, module_name, - ast_overload, parent_dir, compiler_options.import_paths, allow_implicit_casting); - if (res.ok) { - unit = res.result; - } else { - return res.error; - } + AST::Module_t *ast_m = AST::down_cast2(&ast); + Result res = symbol_table_visitor(al, lm, symtab, *ast_m, diagnostics, main_module, module_name, + ast_overload, parent_dir, compiler_options.import_paths, allow_implicit_casting); + if (res.ok) { + unit = res.result; } else { - ast_i = AST::down_cast2(&ast); - Result res = symbol_table_visitor(al, lm, symtab, *ast_i, diagnostics, main_module, module_name, - ast_overload, parent_dir, compiler_options.import_paths, allow_implicit_casting); - if (res.ok) { - unit = res.result; - } else { - return res.error; - } + return res.error; } ASR::TranslationUnit_t *tu = ASR::down_cast2(unit); @@ -8578,23 +8382,12 @@ Result python_ast_to_asr(Allocator &al, LocationManager #endif if (!compiler_options.symtab_only) { - if (!is_interactive) { - auto res2 = body_visitor(al, lm, *ast_m, diagnostics, unit, main_module, module_name, - ast_overload, allow_implicit_casting); - if (res2.ok) { - tu = res2.result; - } else { - return res2.error; - } + auto res2 = body_visitor(al, lm, *ast_m, diagnostics, unit, main_module, module_name, + ast_overload, allow_implicit_casting, eval_count); + if (res2.ok) { + tu = res2.result; } else { - LCOMPILERS_ASSERT(ast_i != nullptr); - auto res2 = body_visitor(al, lm, *ast_i, diagnostics, unit, main_module, module_name, - ast_overload, allow_implicit_casting); - if (res2.ok) { - tu = res2.result; - } else { - return res2.error; - } + return res2.error; } if (compiler_options.po.dump_all_passes) { std::ofstream outfile ("pass_00_initial_asr_02.clj"); diff --git a/src/lpython/semantics/python_ast_to_asr.h b/src/lpython/semantics/python_ast_to_asr.h index ec05cdc4ca..b53a2137b2 100644 --- a/src/lpython/semantics/python_ast_to_asr.h +++ b/src/lpython/semantics/python_ast_to_asr.h @@ -8,7 +8,7 @@ namespace LCompilers::LPython { Result python_ast_to_asr(Allocator &al, LocationManager &lm, SymbolTable* symtab, LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, CompilerOptions &compiler_options, - bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting=false, bool is_interactive=false); + bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting=false, size_t eval_count=0); int save_pyc_files(const ASR::TranslationUnit_t &u, std::string infile); From 150552349b23fcbf5d8bff68284d70fb2aa4e68e Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 12 May 2024 09:42:25 +0530 Subject: [PATCH 9/9] update according to code review suggestion --- src/bin/lpython.cpp | 6 +++++- src/lpython/python_evaluator.cpp | 13 +++++++------ src/lpython/python_evaluator.h | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index d0cebae496..dcf30df425 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -1935,7 +1935,6 @@ int main(int argc, char *argv[]) compiler_options.use_colors = !arg_no_color; compiler_options.indent = !arg_no_indent; - // if (fmt) { // return format(arg_fmt_file, arg_fmt_inplace, !arg_fmt_no_color, // arg_fmt_indent, arg_fmt_indent_unit, compiler_options); @@ -1982,12 +1981,17 @@ int main(int argc, char *argv[]) } if (arg_files.size() == 0) { +#ifdef HAVE_LFORTRAN_LLVM lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); lpython_pass_manager.use_default_passes(); compiler_options.po.disable_main = true; compiler_options.emit_debug_line_column = false; compiler_options.generate_object_code = false; return interactive_python_repl(lpython_pass_manager, compiler_options, arg_v); +#else + std::cerr << "Interactive prompt requires the LLVM backend to be enabled. Recompile with `WITH_LLVM=yes`." << std::endl; + return 1; +#endif } // TODO: for now we ignore the other filenames, only handle diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index d0894abe27..f7314fcb32 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -1,15 +1,16 @@ -#include "libasr/asr_scopes.h" -#include "lpython/python_ast.h" #include +#include +#include #include #include +#include +#include +#include #include #include #include -#include -#include -#include +#include #ifdef HAVE_LFORTRAN_LLVM #include @@ -31,8 +32,8 @@ PythonCompiler::PythonCompiler(CompilerOptions compiler_options) al{1024*1024}, #ifdef HAVE_LFORTRAN_LLVM e{std::make_unique()}, - eval_count{1}, #endif + eval_count{1}, compiler_options{compiler_options}, symbol_table{nullptr} { diff --git a/src/lpython/python_evaluator.h b/src/lpython/python_evaluator.h index 8ec6f632cd..9cba5267ed 100644 --- a/src/lpython/python_evaluator.h +++ b/src/lpython/python_evaluator.h @@ -71,8 +71,8 @@ class PythonCompiler Allocator al; #ifdef HAVE_LFORTRAN_LLVM std::unique_ptr e; - size_t eval_count; #endif + int eval_count; CompilerOptions compiler_options; SymbolTable *symbol_table; std::string run_fn;