From abead67d5346c2983b41cb9b241abe329e86bf13 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Tue, 28 May 2024 17:46:08 +0530 Subject: [PATCH] support printing u32 and u64 in REPL --- src/bin/lpython.cpp | 12 +++ src/libasr/pass/global_stmts.cpp | 17 ++++ src/lpython/python_evaluator.cpp | 30 ++++-- src/lpython/python_evaluator.h | 4 +- src/lpython/tests/test_llvm.cpp | 162 +++++++++++++++++++++++++++++++ 5 files changed, 218 insertions(+), 7 deletions(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index dcf30df425..98f5edc4ef 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -900,6 +900,18 @@ int interactive_python_repl( std::cout << r.i64 << std::endl; break; } + case (LCompilers::PythonCompiler::EvalResult::unsignedInteger4) : { + if (verbose) std::cout << "Return type: unsigned integer" << 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) 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) section("Result:"); diff --git a/src/libasr/pass/global_stmts.cpp b/src/libasr/pass/global_stmts.cpp index 8a9c35f89e..f962103293 100644 --- a/src/libasr/pass/global_stmts.cpp +++ b/src/libasr/pass/global_stmts.cpp @@ -62,6 +62,23 @@ void pass_wrap_global_stmts(Allocator &al, fn_scope->add_symbol(std::string(var_name), down_cast(return_var)); target = return_var_ref; idx++; + } else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::UnsignedInteger) { + s.from_str(al, fn_name_s + std::to_string(idx)); + var_name = s.c_str(al); + + int a_kind = down_cast(ASRUtils::expr_type(value))->m_kind; + + type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc, a_kind)); + return_var = ASR::make_Variable_t(al, loc, + fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, + ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::BindC, + ASR::Public, ASR::presenceType::Required, false); + return_var_ref = EXPR(ASR::make_Var_t(al, loc, + down_cast(return_var))); + fn_scope->add_symbol(std::string(var_name), down_cast(return_var)); + target = return_var_ref; + idx++; } else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Real) { s.from_str(al, fn_name_s + std::to_string(idx)); var_name = s.c_str(al); diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index 9e1452b4e9..b3b0898a1d 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -128,13 +128,31 @@ Result PythonCompiler::evaluate( e->add_module(std::move(m)); if (call_run_fn) { if (return_type == "integer4") { - int32_t r = e->int32fn(run_fn); - result.type = EvalResult::integer4; - result.i32 = r; + 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) { + uint32_t r = e->int32fn(run_fn); + result.type = EvalResult::unsignedInteger4; + result.u32 = r; + } else { + 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; + 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) { + uint64_t r = e->int64fn(run_fn); + result.type = EvalResult::unsignedInteger8; + result.u64 = r; + } else { + 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; diff --git a/src/lpython/python_evaluator.h b/src/lpython/python_evaluator.h index 58686c47b9..c6aeee6d26 100644 --- a/src/lpython/python_evaluator.h +++ b/src/lpython/python_evaluator.h @@ -37,11 +37,13 @@ class PythonCompiler struct EvalResult { enum { - integer4, integer8, real4, real8, complex4, complex8, statement, none + integer4, integer8, unsignedInteger4, unsignedInteger8, real4, real8, complex4, complex8, statement, none } type; union { int32_t i32; int64_t i64; + uint32_t u32; + uint64_t u64; float f32; double f64; struct {float re, im;} c32; diff --git a/src/lpython/tests/test_llvm.cpp b/src/lpython/tests/test_llvm.cpp index 08e37634d6..9f89571fe8 100644 --- a/src/lpython/tests/test_llvm.cpp +++ b/src/lpython/tests/test_llvm.cpp @@ -784,3 +784,165 @@ TEST_CASE("PythonCompiler i64 declaration") { CHECK(r.result.type == PythonCompiler::EvalResult::integer8); CHECK(r.result.i64 == 14); } + +TEST_CASE("PythonCompiler u32 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("u32(1)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 1); + + r = e.evaluate2("u32(1) + u32(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 3); + + r = e.evaluate2("u32(20) - u32(10)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 10); + + r = e.evaluate2("u32(1) * u32(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 2); + + r = e.evaluate2("u32(3) ** u32(3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 27); + + r = e.evaluate2("u32(4) // u32(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 2); + + r = e.evaluate2("u32(4) / u32(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == 2); +} + +TEST_CASE("PythonCompiler u32 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: u32"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i = u32(5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::statement); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 5); + + r = e.evaluate2("j: u32 = u32(9)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 9); + + r = e.evaluate2("i * j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger4); + CHECK(r.result.u32 == 45); +} + +TEST_CASE("PythonCompiler u64 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("u64(1)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 1); + + r = e.evaluate2("u64(1) + u64(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 3); + + r = e.evaluate2("u64(20) - u64(10)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 10); + + r = e.evaluate2("u64(1) * u64(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 2); + + r = e.evaluate2("u64(3) ** u64(3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 27); + + r = e.evaluate2("u64(4) // u64(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 2); + + r = e.evaluate2("u64(4) / u64(2)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == 2); +} + +TEST_CASE("PythonCompiler u64 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: u64"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i = u64(5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::statement); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 5); + + r = e.evaluate2("j: u64 = u64(9)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 9); + + r = e.evaluate2("i * j"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::unsignedInteger8); + CHECK(r.result.u64 == 45); +}