diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 69f47893f1..43649c57b5 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -986,6 +986,12 @@ int interactive_python_repl( std::cout << std::setprecision(17) << "(" << r.c64.re << ", " << r.c64.im << ")" << std::endl; break; } + case (LCompilers::PythonCompiler::EvalResult::boolean) : { + if (verbose) std::cout << "Return type: logical" << std::endl; + if (verbose) section("Result:"); + std::cout << (r.b ? "True" : "False") << std::endl; + break; + } case (LCompilers::PythonCompiler::EvalResult::string) : { if (verbose) std::cout << "Return type: str" << std::endl; if (verbose) section("Result:"); diff --git a/src/libasr/codegen/evaluator.cpp b/src/libasr/codegen/evaluator.cpp index dadf4fb50d..383271fd7f 100644 --- a/src/libasr/codegen/evaluator.cpp +++ b/src/libasr/codegen/evaluator.cpp @@ -102,6 +102,8 @@ std::string LLVMModule::get_return_type(const std::string &fn_name) return "real4"; } else if (type->isDoubleTy()) { return "real8"; + } else if (type->isIntegerTy(1)) { + return "logical"; } else if (type->isIntegerTy(8)) { return "integer1"; } else if (type->isIntegerTy(16)) { diff --git a/src/libasr/pass/global_stmts.cpp b/src/libasr/pass/global_stmts.cpp index dd0b91790f..87966cd456 100644 --- a/src/libasr/pass/global_stmts.cpp +++ b/src/libasr/pass/global_stmts.cpp @@ -79,6 +79,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::Logical) { + 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_Logical_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 b5aad743c1..836ddaad22 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -208,6 +208,10 @@ Result PythonCompiler::evaluate( result.type = EvalResult::complex8; result.c64.re = r.real(); result.c64.im = r.imag(); + } else if (return_type == "logical") { + bool r = e->execfn(run_fn); + result.type = EvalResult::boolean; + result.b = r; } else if (return_type == "void") { e->execfn(run_fn); result.type = EvalResult::statement; diff --git a/src/lpython/python_evaluator.h b/src/lpython/python_evaluator.h index 882495813d..f5c4d538ec 100644 --- a/src/lpython/python_evaluator.h +++ b/src/lpython/python_evaluator.h @@ -49,6 +49,7 @@ class PythonCompiler real8, complex4, complex8, + boolean, string, statement, none @@ -58,6 +59,7 @@ class PythonCompiler int64_t i64; uint32_t u32; uint64_t u64; + bool b; float f32; double f64; char *str; diff --git a/src/lpython/tests/test_llvm.cpp b/src/lpython/tests/test_llvm.cpp index 8d2b91f919..055e052dd9 100644 --- a/src/lpython/tests/test_llvm.cpp +++ b/src/lpython/tests/test_llvm.cpp @@ -1292,6 +1292,77 @@ TEST_CASE("PythonCompiler u16 declaration") { CHECK(r.result.u32 == 45); } +TEST_CASE("PythonCompiler boolean 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("True"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(r.result.b); + + r = e.evaluate2("False"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(!r.result.b); + + r = e.evaluate2("False or True"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(r.result.b); + + r = e.evaluate2("False and True"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(!r.result.b); +} + +TEST_CASE("PythonCompiler boolean 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("t: bool"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("t = True"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::statement); + r = e.evaluate2("t"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(r.result.b); + + r = e.evaluate2("f: bool = False"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("f"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(!r.result.b); + + r = e.evaluate2("t or f"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(r.result.b); + + r = e.evaluate2("t and f"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::boolean); + CHECK(!r.result.b); +} + TEST_CASE("PythonCompiler string 1") { CompilerOptions cu; cu.po.disable_main = true;