|
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>
|
@@ -743,6 +744,11 @@ void print_time_report(std::vector<std::pair<std::string, double>> ×, bool
|
743 | 744 |
|
744 | 745 | #ifdef HAVE_LFORTRAN_LLVM
|
745 | 746 |
|
| 747 | +void section(const std::string &s) |
| 748 | +{ |
| 749 | + std::cout << color(LCompilers::style::bold) << color(LCompilers::fg::blue) << s << color(LCompilers::style::reset) << color(LCompilers::fg::reset) << std::endl; |
| 750 | +} |
| 751 | + |
746 | 752 | int emit_llvm(const std::string &infile,
|
747 | 753 | const std::string &runtime_library_dir,
|
748 | 754 | LCompilers::PassManager& pass_manager,
|
@@ -792,6 +798,157 @@ int emit_llvm(const std::string &infile,
|
792 | 798 | return 0;
|
793 | 799 | }
|
794 | 800 |
|
| 801 | +int interactive_python_repl( |
| 802 | + LCompilers::PassManager& pass_manager, |
| 803 | + CompilerOptions &compiler_options, |
| 804 | + bool verbose) |
| 805 | +{ |
| 806 | + Allocator al(4*1024); |
| 807 | + compiler_options.interactive = true; |
| 808 | + LCompilers::PythonCompiler fe(compiler_options); |
| 809 | + LCompilers::diag::Diagnostics diagnostics; |
| 810 | + LCompilers::LocationManager lm; |
| 811 | + std::vector<std::pair<std::string, double>> times; |
| 812 | + LCompilers::PythonCompiler::EvalResult r; |
| 813 | + |
| 814 | + std::string code_string; |
| 815 | + std::cout << ">>> "; |
| 816 | + size_t cell_count = 0; |
| 817 | + for (std::string input; std::getline(std::cin, input);) { |
| 818 | + if (input == "exit" || input == "quit") { |
| 819 | + return 0; |
| 820 | + } |
| 821 | + |
| 822 | + if ((input.rfind("def", 0) == 0) || |
| 823 | + (input.rfind("for", 0) == 0) || |
| 824 | + (input.rfind("if", 0) == 0) || |
| 825 | + (input.rfind("else", 0) == 0) || |
| 826 | + (input.rfind("elif", 0) == 0) || |
| 827 | + (input.rfind("class", 0) == 0) || |
| 828 | + (input.rfind('@', 0) == 0) || |
| 829 | + (input.rfind(' ', 0) == 0) || |
| 830 | + (input.rfind('\t', 0) == 0)) { |
| 831 | + // start of a block |
| 832 | + code_string += input + "\n"; |
| 833 | + std::cout << "... "; |
| 834 | + continue; |
| 835 | + } |
| 836 | + code_string += input + "\n"; |
| 837 | + |
| 838 | + { |
| 839 | + cell_count++; |
| 840 | + LCompilers::LocationManager::FileLocations fl; |
| 841 | + fl.in_filename = "input"; |
| 842 | + std::ofstream out("input"); |
| 843 | + out << code_string; |
| 844 | + lm.files.push_back(fl); |
| 845 | + lm.init_simple(code_string); |
| 846 | + lm.file_ends.push_back(code_string.size()); |
| 847 | + } |
| 848 | + |
| 849 | + try { |
| 850 | + auto evaluation_start_time = std::chrono::high_resolution_clock::now(); |
| 851 | + LCompilers::Result<LCompilers::PythonCompiler::EvalResult> |
| 852 | + res = fe.evaluate(code_string, verbose, lm, pass_manager, diagnostics); |
| 853 | + if (res.ok) { |
| 854 | + r = res.result; |
| 855 | + } else { |
| 856 | + LCOMPILERS_ASSERT(diagnostics.has_error()) |
| 857 | + std::cerr << diagnostics.render(lm, compiler_options); |
| 858 | + diagnostics.clear(); |
| 859 | + code_string = ""; |
| 860 | + std::cout << ">>> "; |
| 861 | + continue; |
| 862 | + } |
| 863 | + |
| 864 | + auto evaluation_end_time = std::chrono::high_resolution_clock::now(); |
| 865 | + times.push_back(std::make_pair("evalution " + std::to_string(cell_count), std::chrono::duration |
| 866 | + <double, std::milli>(evaluation_start_time - evaluation_end_time).count())); |
| 867 | + |
| 868 | + } catch (const LCompilers::LCompilersException &e) { |
| 869 | + std::cerr << "Internal Compiler Error: Unhandled exception" << std::endl; |
| 870 | + std::vector<LCompilers::StacktraceItem> d = e.stacktrace_addresses(); |
| 871 | + get_local_addresses(d); |
| 872 | + get_local_info(d); |
| 873 | + std::cerr << stacktrace2str(d, LCompilers::stacktrace_depth); |
| 874 | + std::cerr << e.name() + ": " << e.msg() << std::endl; |
| 875 | + |
| 876 | + code_string = ""; |
| 877 | + std::cout << ">>> "; |
| 878 | + continue; |
| 879 | + } |
| 880 | + |
| 881 | + if (verbose) { |
| 882 | + section("AST:"); |
| 883 | + std::cout << r.ast << std::endl; |
| 884 | + section("ASR:"); |
| 885 | + std::cout << r.asr << std::endl; |
| 886 | + section("LLVM IR:"); |
| 887 | + std::cout << r.llvm_ir << std::endl; |
| 888 | + } |
| 889 | + |
| 890 | + switch (r.type) { |
| 891 | + case (LCompilers::PythonCompiler::EvalResult::integer4) : { |
| 892 | + if (verbose) std::cout << "Return type: integer" << std::endl; |
| 893 | + if (verbose) section("Result:"); |
| 894 | + std::cout << r.i32 << std::endl; |
| 895 | + break; |
| 896 | + } |
| 897 | + case (LCompilers::PythonCompiler::EvalResult::integer8) : { |
| 898 | + if (verbose) std::cout << "Return type: integer(8)" << std::endl; |
| 899 | + if (verbose) section("Result:"); |
| 900 | + std::cout << r.i64 << std::endl; |
| 901 | + break; |
| 902 | + } |
| 903 | + case (LCompilers::PythonCompiler::EvalResult::real4) : { |
| 904 | + if (verbose) std::cout << "Return type: real" << std::endl; |
| 905 | + if (verbose) section("Result:"); |
| 906 | + std::cout << std::setprecision(8) << r.f32 << std::endl; |
| 907 | + break; |
| 908 | + } |
| 909 | + case (LCompilers::PythonCompiler::EvalResult::real8) : { |
| 910 | + if (verbose) std::cout << "Return type: real(8)" << std::endl; |
| 911 | + if (verbose) section("Result:"); |
| 912 | + std::cout << std::setprecision(17) << r.f64 << std::endl; |
| 913 | + break; |
| 914 | + } |
| 915 | + case (LCompilers::PythonCompiler::EvalResult::complex4) : { |
| 916 | + if (verbose) std::cout << "Return type: complex" << std::endl; |
| 917 | + if (verbose) section("Result:"); |
| 918 | + std::cout << std::setprecision(8) << "(" << r.c32.re << ", " << r.c32.im << ")" << std::endl; |
| 919 | + break; |
| 920 | + } |
| 921 | + case (LCompilers::PythonCompiler::EvalResult::complex8) : { |
| 922 | + if (verbose) std::cout << "Return type: complex(8)" << std::endl; |
| 923 | + if (verbose) section("Result:"); |
| 924 | + std::cout << std::setprecision(17) << "(" << r.c64.re << ", " << r.c64.im << ")" << std::endl; |
| 925 | + break; |
| 926 | + } |
| 927 | + case (LCompilers::PythonCompiler::EvalResult::statement) : { |
| 928 | + if (verbose) { |
| 929 | + std::cout << "Return type: none" << std::endl; |
| 930 | + section("Result:"); |
| 931 | + std::cout << "(statement)" << std::endl; |
| 932 | + } |
| 933 | + break; |
| 934 | + } |
| 935 | + case (LCompilers::PythonCompiler::EvalResult::none) : { |
| 936 | + if (verbose) { |
| 937 | + std::cout << "Return type: none" << std::endl; |
| 938 | + section("Result:"); |
| 939 | + std::cout << "(nothing to execute)" << std::endl; |
| 940 | + } |
| 941 | + break; |
| 942 | + } |
| 943 | + default : throw LCompilers::LCompilersException("Return type not supported"); |
| 944 | + } |
| 945 | + |
| 946 | + code_string = ""; |
| 947 | + std::cout << ">>> "; |
| 948 | + } |
| 949 | + return 0; |
| 950 | +} |
| 951 | + |
795 | 952 | /*
|
796 | 953 | Compiles python to object file, if `to_jit` is false
|
797 | 954 | otherwise execute python code using llvm JIT
|
@@ -1824,8 +1981,17 @@ int main(int argc, char *argv[])
|
1824 | 1981 | }
|
1825 | 1982 |
|
1826 | 1983 | if (arg_files.size() == 0) {
|
1827 |
| - std::cerr << "Interactive prompt is not implemented yet in LPython" << std::endl; |
| 1984 | +#ifdef HAVE_LFORTRAN_LLVM |
| 1985 | + lpython_pass_manager.parse_pass_arg(arg_pass, skip_pass); |
| 1986 | + lpython_pass_manager.use_default_passes(); |
| 1987 | + compiler_options.po.disable_main = true; |
| 1988 | + compiler_options.emit_debug_line_column = false; |
| 1989 | + compiler_options.generate_object_code = false; |
| 1990 | + return interactive_python_repl(lpython_pass_manager, compiler_options, arg_v); |
| 1991 | +#else |
| 1992 | + std::cerr << "Interactive prompt requires the LLVM backend to be enabled. Recompile with `WITH_LLVM=yes`." << std::endl; |
1828 | 1993 | return 1;
|
| 1994 | +#endif |
1829 | 1995 | }
|
1830 | 1996 |
|
1831 | 1997 | // TODO: for now we ignore the other filenames, only handle
|
|
0 commit comments