|
33 | 33 | #include <lpython/python_serialization.h>
|
34 | 34 | #include <lpython/parser/tokenizer.h>
|
35 | 35 | #include <lpython/parser/parser.h>
|
| 36 | +#include <libasr/exception.h> |
36 | 37 |
|
37 | 38 | #include <cpp-terminal/terminal.h>
|
38 | 39 | #include <cpp-terminal/prompt0.h>
|
@@ -792,6 +793,123 @@ int emit_llvm(const std::string &infile,
|
792 | 793 | return 0;
|
793 | 794 | }
|
794 | 795 |
|
| 796 | +int interactive_python_repl( |
| 797 | + LCompilers::PassManager& pass_manager, |
| 798 | + CompilerOptions &compiler_options, |
| 799 | + bool time_report) |
| 800 | +{ |
| 801 | + Allocator al(4*1024); |
| 802 | + |
| 803 | + LCompilers::diag::Diagnostics diagnostics; |
| 804 | + LCompilers::LocationManager lm; |
| 805 | + std::vector<std::pair<std::string, double>> times; |
| 806 | + std::string infile; |
| 807 | + |
| 808 | + std::string code_string; |
| 809 | + std::cout << ">>> "; |
| 810 | + size_t cell_count = 0; |
| 811 | + for (std::string input; std::getline(std::cin, input);) { |
| 812 | + |
| 813 | + if (input == "exit" || input == "quit") // exit condition |
| 814 | + return 0; |
| 815 | + |
| 816 | + if ((input.rfind("def", 0) == 0) || |
| 817 | + (input.rfind("for", 0) == 0) || |
| 818 | + (input.rfind("if", 0) == 0) || |
| 819 | + (input.rfind("else", 0) == 0) || |
| 820 | + (input.rfind("elif", 0) == 0) || |
| 821 | + (input.rfind("class", 0) == 0) || |
| 822 | + (input.rfind(' ', 0) == 0) || |
| 823 | + (input.rfind('\t', 0) == 0)) { |
| 824 | + // start of a block |
| 825 | + code_string += input + "\n"; |
| 826 | + std::cout << "... "; |
| 827 | + continue; |
| 828 | + } |
| 829 | + code_string += input + "\n"; |
| 830 | + |
| 831 | + // std::cout << "code block: \n" << code_string; |
| 832 | + |
| 833 | + { |
| 834 | + cell_count++; |
| 835 | + LCompilers::LocationManager::FileLocations fl; |
| 836 | + infile = "stdin" + std::to_string(cell_count); |
| 837 | + fl.in_filename = infile; |
| 838 | + lm.files.push_back(fl); |
| 839 | + lm.init_simple(code_string); |
| 840 | + lm.file_ends.push_back(code_string.size()); |
| 841 | + } |
| 842 | + |
| 843 | + /* parse and run */ |
| 844 | + // parsing string to AST |
| 845 | + auto parsing_start = std::chrono::high_resolution_clock::now(); |
| 846 | + // ???: change `parse_python_file` to `parse` or `parse_string` |
| 847 | + LCompilers::Result<LCompilers::LPython::AST::Module_t*> r = LCompilers::LPython::parse(al, code_string, 0, diagnostics); |
| 848 | + auto parsing_end = std::chrono::high_resolution_clock::now(); |
| 849 | + times.push_back(std::make_pair("Parsing", std::chrono::duration<double, std::milli>(parsing_end - parsing_start).count())); |
| 850 | + std::cerr << diagnostics.render(lm, compiler_options); |
| 851 | + if (!r.ok) { |
| 852 | + LCOMPILERS_ASSERT(diagnostics.has_error()) |
| 853 | + print_time_report(times, time_report); |
| 854 | + return 1; |
| 855 | + } |
| 856 | + |
| 857 | + // AST -> ASR |
| 858 | + LCompilers::LPython::AST::ast_t* ast = (LCompilers::LPython::AST::ast_t*)r.result; |
| 859 | + diagnostics.diagnostics.clear(); |
| 860 | + auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); |
| 861 | + LCompilers::Result<LCompilers::ASR::TranslationUnit_t*> |
| 862 | + r1 = LCompilers::LPython::python_ast_to_asr(al, lm, nullptr, *ast, diagnostics, compiler_options, |
| 863 | + !(false && compiler_options.po.disable_main), "__main__", infile); |
| 864 | + |
| 865 | + auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); |
| 866 | + times.push_back(std::make_pair("AST to ASR", std::chrono::duration<double, std::milli>(ast_to_asr_end - ast_to_asr_start).count())); |
| 867 | + std::cerr << diagnostics.render(lm, compiler_options); |
| 868 | + if (!r1.ok) { |
| 869 | + LCOMPILERS_ASSERT(diagnostics.has_error()) |
| 870 | + print_time_report(times, time_report); |
| 871 | + return 2; |
| 872 | + } |
| 873 | + LCompilers::ASR::TranslationUnit_t* asr = r1.result; |
| 874 | + diagnostics.diagnostics.clear(); |
| 875 | + |
| 876 | + LCompilers::PythonCompiler fe(compiler_options); |
| 877 | + LCompilers::LLVMEvaluator e(compiler_options.target); |
| 878 | + std::unique_ptr<LCompilers::LLVMModule> m; |
| 879 | + auto asr_to_llvm_start = std::chrono::high_resolution_clock::now(); |
| 880 | + LCompilers::Result<std::unique_ptr<LCompilers::LLVMModule>> |
| 881 | + res = fe.get_llvm3(*asr, pass_manager, diagnostics, infile); |
| 882 | + auto asr_to_llvm_end = std::chrono::high_resolution_clock::now(); |
| 883 | + times.push_back(std::make_pair("ASR to LLVM", std::chrono::duration<double, std::milli>(asr_to_llvm_end - asr_to_llvm_start).count())); |
| 884 | + |
| 885 | + std::cerr << diagnostics.render(lm, compiler_options); |
| 886 | + if (!res.ok) { |
| 887 | + LCOMPILERS_ASSERT(diagnostics.has_error()) |
| 888 | + print_time_report(times, time_report); |
| 889 | + return 3; |
| 890 | + } |
| 891 | + m = std::move(res.result); |
| 892 | + |
| 893 | + bool call_init = false; |
| 894 | + bool call_stmts = false; |
| 895 | + if (m->get_return_type("__module___main_____main__global_init") == "void") |
| 896 | + call_init = true; |
| 897 | + if (m->get_return_type("__module___main_____main__global_stmts") == "void") |
| 898 | + call_stmts = true; |
| 899 | + |
| 900 | + e.add_module(std::move(m)); |
| 901 | + if (call_init) |
| 902 | + e.voidfn("__module___main_____main__global_init"); |
| 903 | + if (call_stmts) |
| 904 | + e.voidfn("__module___main_____main__global_stmts"); |
| 905 | + /* end parse and run */ |
| 906 | + |
| 907 | + code_string = ""; |
| 908 | + std::cout << ">>> "; |
| 909 | + } |
| 910 | + return 0; |
| 911 | +} |
| 912 | + |
795 | 913 | /*
|
796 | 914 | Compiles python to object file, if `to_jit` is false
|
797 | 915 | otherwise execute python code using llvm JIT
|
@@ -1785,6 +1903,9 @@ int main(int argc, char *argv[])
|
1785 | 1903 | compiler_options.use_colors = !arg_no_color;
|
1786 | 1904 | compiler_options.indent = !arg_no_indent;
|
1787 | 1905 |
|
| 1906 | + lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); |
| 1907 | + lpython_pass_manager.use_default_passes(); |
| 1908 | + |
1788 | 1909 | // if (fmt) {
|
1789 | 1910 | // return format(arg_fmt_file, arg_fmt_inplace, !arg_fmt_no_color,
|
1790 | 1911 | // arg_fmt_indent, arg_fmt_indent_unit, compiler_options);
|
@@ -1831,8 +1952,10 @@ int main(int argc, char *argv[])
|
1831 | 1952 | }
|
1832 | 1953 |
|
1833 | 1954 | if (arg_files.size() == 0) {
|
1834 |
| - std::cerr << "Interactive prompt is not implemented yet in LPython" << std::endl; |
1835 |
| - return 1; |
| 1955 | + compiler_options.po.disable_main = true; |
| 1956 | + compiler_options.emit_debug_line_column = false; |
| 1957 | + compiler_options.generate_object_code = false; |
| 1958 | + return interactive_python_repl(lpython_pass_manager, compiler_options, time_report); |
1836 | 1959 | }
|
1837 | 1960 |
|
1838 | 1961 | // TODO: for now we ignore the other filenames, only handle
|
@@ -1875,7 +1998,6 @@ int main(int argc, char *argv[])
|
1875 | 1998 | // return emit_c_preprocessor(arg_file, compiler_options);
|
1876 | 1999 | // }
|
1877 | 2000 |
|
1878 |
| - lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); |
1879 | 2001 | if (show_tokens) {
|
1880 | 2002 | return emit_tokens(arg_file, true, compiler_options);
|
1881 | 2003 | }
|
@@ -1917,7 +2039,6 @@ int main(int argc, char *argv[])
|
1917 | 2039 | return 1;
|
1918 | 2040 | #endif
|
1919 | 2041 | }
|
1920 |
| - lpython_pass_manager.use_default_passes(); |
1921 | 2042 | if (show_llvm) {
|
1922 | 2043 | #ifdef HAVE_LFORTRAN_LLVM
|
1923 | 2044 | return emit_llvm(arg_file, runtime_library_dir, lpython_pass_manager, compiler_options);
|
|
0 commit comments