diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 98f5edc4ef..a7241644a1 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -888,50 +888,74 @@ int interactive_python_repl( } switch (r.type) { + case (LCompilers::PythonCompiler::EvalResult::integer1) : { + if (verbose) std::cout << "Return type: i8" << std::endl; + if (verbose) section("Result:"); + std::cout << r.i32 << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::integer2) : { + if (verbose) std::cout << "Return type: i16" << std::endl; + if (verbose) section("Result:"); + std::cout << r.i64 << std::endl; + break; + } case (LCompilers::PythonCompiler::EvalResult::integer4) : { - if (verbose) std::cout << "Return type: integer" << std::endl; + if (verbose) std::cout << "Return type: i32" << 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) std::cout << "Return type: i64" << std::endl; if (verbose) section("Result:"); std::cout << r.i64 << std::endl; break; } + case (LCompilers::PythonCompiler::EvalResult::unsignedInteger1) : { + if (verbose) std::cout << "Return type: u8" << std::endl; + if (verbose) section("Result:"); + std::cout << r.u32 << std::endl; + break; + } + case (LCompilers::PythonCompiler::EvalResult::unsignedInteger2) : { + if (verbose) std::cout << "Return type: u16" << std::endl; + if (verbose) section("Result:"); + std::cout << r.u64 << std::endl; + break; + } case (LCompilers::PythonCompiler::EvalResult::unsignedInteger4) : { - if (verbose) std::cout << "Return type: unsigned integer" << std::endl; + if (verbose) std::cout << "Return type: u32" << std::endl; if (verbose) section("Result:"); std::cout << r.u32 << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::unsignedInteger8) : { - if (verbose) std::cout << "Return type: unsigned integer(8)" << std::endl; + if (verbose) std::cout << "Return type: u64" << std::endl; if (verbose) section("Result:"); std::cout << r.u64 << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::real4) : { - if (verbose) std::cout << "Return type: real" << std::endl; + if (verbose) std::cout << "Return type: f32" << 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) std::cout << "Return type: f64" << 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) std::cout << "Return type: c32" << 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) std::cout << "Return type: c64" << std::endl; if (verbose) section("Result:"); std::cout << std::setprecision(17) << "(" << r.c64.re << ", " << r.c64.im << ")" << std::endl; break; diff --git a/src/libasr/codegen/evaluator.cpp b/src/libasr/codegen/evaluator.cpp index f2f1a7fcc0..2e00aec308 100644 --- a/src/libasr/codegen/evaluator.cpp +++ b/src/libasr/codegen/evaluator.cpp @@ -102,6 +102,10 @@ std::string LLVMModule::get_return_type(const std::string &fn_name) return "real4"; } else if (type->isDoubleTy()) { return "real8"; + } else if (type->isIntegerTy(8)) { + return "integer1"; + } else if (type->isIntegerTy(16)) { + return "integer2"; } else if (type->isIntegerTy(32)) { return "integer4"; } else if (type->isIntegerTy(64)) { @@ -269,6 +273,18 @@ intptr_t LLVMEvaluator::get_symbol_address(const std::string &name) { return (intptr_t)cantFail(std::move(addr0)); } +int8_t LLVMEvaluator::int8fn(const std::string &name) { + intptr_t addr = get_symbol_address(name); + int8_t (*f)() = (int8_t (*)())addr; + return f(); +} + +int16_t LLVMEvaluator::int16fn(const std::string &name) { + intptr_t addr = get_symbol_address(name); + int16_t (*f)() = (int16_t (*)())addr; + return f(); +} + int32_t LLVMEvaluator::int32fn(const std::string &name) { intptr_t addr = get_symbol_address(name); int32_t (*f)() = (int32_t (*)())addr; diff --git a/src/libasr/codegen/evaluator.h b/src/libasr/codegen/evaluator.h index 9c8e1a21c7..2fc6a50984 100644 --- a/src/libasr/codegen/evaluator.h +++ b/src/libasr/codegen/evaluator.h @@ -52,6 +52,8 @@ class LLVMEvaluator void add_module(std::unique_ptr mod); void add_module(std::unique_ptr m); intptr_t get_symbol_address(const std::string &name); + int8_t int8fn(const std::string &name); + int16_t int16fn(const std::string &name); int32_t int32fn(const std::string &name); int64_t int64fn(const std::string &name); bool boolfn(const std::string &name); diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index b3b0898a1d..a717667fe3 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -127,7 +127,33 @@ Result PythonCompiler::evaluate( e->add_module(std::move(m)); if (call_run_fn) { - if (return_type == "integer4") { + if (return_type == "integer1") { + ASR::symbol_t *fn = ASR::down_cast(symbol_table->resolve_symbol(module_name)) + ->m_symtab->get_symbol(run_fn); + LCOMPILERS_ASSERT(fn) + if (ASRUtils::get_FunctionType(fn)->m_return_var_type->type == ASR::ttypeType::UnsignedInteger) { + uint8_t r = e->int8fn(run_fn); + result.type = EvalResult::unsignedInteger1; + result.u32 = r; + } else { + int8_t r = e->int8fn(run_fn); + result.type = EvalResult::integer1; + result.i32 = r; + } + } else if (return_type == "integer2") { + ASR::symbol_t *fn = ASR::down_cast(symbol_table->resolve_symbol(module_name)) + ->m_symtab->get_symbol(run_fn); + LCOMPILERS_ASSERT(fn) + if (ASRUtils::get_FunctionType(fn)->m_return_var_type->type == ASR::ttypeType::UnsignedInteger) { + uint16_t r = e->int16fn(run_fn); + result.type = EvalResult::unsignedInteger2; + result.u32 = r; + } else { + int16_t r = e->int16fn(run_fn); + result.type = EvalResult::integer2; + result.i32 = r; + } + } else if (return_type == "integer4") { ASR::symbol_t *fn = ASR::down_cast(symbol_table->resolve_symbol(module_name)) ->m_symtab->get_symbol(run_fn); LCOMPILERS_ASSERT(fn) diff --git a/src/lpython/python_evaluator.h b/src/lpython/python_evaluator.h index c6aeee6d26..05e0e61023 100644 --- a/src/lpython/python_evaluator.h +++ b/src/lpython/python_evaluator.h @@ -37,7 +37,20 @@ class PythonCompiler struct EvalResult { enum { - integer4, integer8, unsignedInteger4, unsignedInteger8, real4, real8, complex4, complex8, statement, none + integer1, + integer2, + unsignedInteger1, + unsignedInteger2, + integer4, + integer8, + unsignedInteger4, + unsignedInteger8, + real4, + real8, + complex4, + complex8, + statement, + none } type; union { int32_t i32; diff --git a/src/lpython/tests/test_llvm.cpp b/src/lpython/tests/test_llvm.cpp index 9f89571fe8..29bb414772 100644 --- a/src/lpython/tests/test_llvm.cpp +++ b/src/lpython/tests/test_llvm.cpp @@ -946,3 +946,327 @@ TEST_CASE("PythonCompiler u64 declaration") { CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); CHECK(r.result.u64 == 45); } + +TEST_CASE("PythonCompiler i8 expressions") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i8(1)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 1); + + r = e.evaluate2("i8(1) + i8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 3); + + r = e.evaluate2("i8(1) - i8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == -1); + + r = e.evaluate2("i8(1) * i8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 2); + + r = e.evaluate2("i8(3) ** i8(3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 27); + + r = e.evaluate2("i8(4) // i8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 2); + + r = e.evaluate2("i8(4) / i8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == 2); +} + +TEST_CASE("PythonCompiler i8 declaration") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i: i8"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i = i8(5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::statement); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 5); + + r = e.evaluate2("j: i8 = i8(9)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 9); + + r = e.evaluate2("i + j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer1); + CHECK(r.result.i32 == 14); +} + +TEST_CASE("PythonCompiler u8 expressions") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("u8(1)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 1); + + r = e.evaluate2("u8(1) + u8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 3); + + r = e.evaluate2("u8(20) - u8(10)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 10); + + r = e.evaluate2("u8(1) * u8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 2); + + r = e.evaluate2("u8(3) ** u8(3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 27); + + r = e.evaluate2("u8(4) // u8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 2); + + r = e.evaluate2("u8(4) / u8(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == 2); +} + +TEST_CASE("PythonCompiler u8 declaration") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i: u8"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i = u8(5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::statement); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 5); + + r = e.evaluate2("j: u8 = u8(9)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 9); + + r = e.evaluate2("i * j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger1); + CHECK(r.result.u32 == 45); +} + +TEST_CASE("PythonCompiler i16 expressions") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i16(1)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 1); + + r = e.evaluate2("i16(1) + i16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 3); + + r = e.evaluate2("i16(1) - i16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == -1); + + r = e.evaluate2("i16(1) * i16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 2); + + r = e.evaluate2("i16(3) ** i16(3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 27); + + r = e.evaluate2("i16(4) // i16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 2); + + r = e.evaluate2("i16(4) / i16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == 2); +} + +TEST_CASE("PythonCompiler i16 declaration") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i: i16"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i = i16(5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::statement); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 5); + + r = e.evaluate2("j: i16 = i16(9)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 9); + + r = e.evaluate2("i + j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer2); + CHECK(r.result.i32 == 14); +} + +TEST_CASE("PythonCompiler u16 expressions") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("u16(1)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 1); + + r = e.evaluate2("u16(1) + u16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 3); + + r = e.evaluate2("u16(20) - u16(10)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 10); + + r = e.evaluate2("u16(1) * u16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 2); + + r = e.evaluate2("u16(3) ** u16(3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 27); + + r = e.evaluate2("u16(4) // u16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 2); + + r = e.evaluate2("u16(4) / u16(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == 2); +} + +TEST_CASE("PythonCompiler u16 declaration") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i: u16"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i = u16(5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::statement); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 5); + + r = e.evaluate2("j: u16 = u16(9)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 9); + + r = e.evaluate2("i * j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger2); + CHECK(r.result.u32 == 45); +}