Skip to content

Commit

Permalink
Printing top-level Expressions (lcompilers#2716)
Browse files Browse the repository at this point in the history
* printing top level expressions

* test cases for i32 and i64

* fix typo

* update according to code review suggestions

* Update src/lpython/semantics/python_ast_to_asr.cpp

Co-authored-by: Shaikh Ubaid <[email protected]>

---------

Co-authored-by: Shaikh Ubaid <[email protected]>
  • Loading branch information
Vipul-Cariappa and Shaikh-Ubaid authored May 26, 2024
1 parent 13bb54e commit 2420448
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 6 deletions.
37 changes: 36 additions & 1 deletion src/lpython/python_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,48 @@ Result<PythonCompiler::EvalResult> PythonCompiler::evaluate(
}

bool call_run_fn = false;
std::string return_type;
if (m->get_return_type(run_fn) != "none") {
call_run_fn = true;
return_type = m->get_return_type(run_fn);
}

e->add_module(std::move(m));
if (call_run_fn) {
e->voidfn(run_fn);
if (return_type == "integer4") {
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;
} else if (return_type == "real4") {
float r = e->floatfn(run_fn);
result.type = EvalResult::real4;
result.f32 = r;
} else if (return_type == "real8") {
double r = e->doublefn(run_fn);
result.type = EvalResult::real8;
result.f64 = r;
} else if (return_type == "complex4") {
std::complex<float> r = e->complex4fn(run_fn);
result.type = EvalResult::complex4;
result.c32.re = r.real();
result.c32.im = r.imag();
} else if (return_type == "complex8") {
std::complex<double> r = e->complex8fn(run_fn);
result.type = EvalResult::complex8;
result.c64.re = r.real();
result.c64.im = r.imag();
} else if (return_type == "void") {
e->voidfn(run_fn);
result.type = EvalResult::statement;
} else if (return_type == "none") {
result.type = EvalResult::none;
} else {
throw LCompilersException("FortranEvaluator::evaluate(): Return type not supported");
}
}

if (call_run_fn) {
Expand Down
8 changes: 4 additions & 4 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6693,10 +6693,10 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
}
this->visit_expr(*x.m_value);

// If tmp is a statement and not an expression
// never cast into expression using ASRUtils::EXPR
// Just ignore and exit the function naturally.
if( tmp && !ASR::is_a<ASR::stmt_t>(*tmp) ) {
if (eval_count == 0 && tmp && !ASR::is_a<ASR::stmt_t>(*tmp)) {
// If tmp is a statement and not an expression
// never cast into expression using ASRUtils::EXPR
// Just ignore and exit the function naturally.
LCOMPILERS_ASSERT(ASR::is_a<ASR::expr_t>(*tmp));
tmp = nullptr;
}
Expand Down
165 changes: 164 additions & 1 deletion src/lpython/tests/test_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,5 +619,168 @@ TEST_CASE("PythonCompiler 1") {
LCompilers::Result<PythonCompiler::EvalResult>
r = e.evaluate2("1");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::none); // TODO: change to integer4 and check the value once printing top level expressions is implemented
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 1);
}

TEST_CASE("PythonCompiler i32 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<PythonCompiler::EvalResult>

r = e.evaluate2("1");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 1);

r = e.evaluate2("1 + 2");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 3);

r = e.evaluate2("1 - 2");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == -1);

r = e.evaluate2("1 * 2");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 2);

r = e.evaluate2("3 ** 3");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 27);

r = e.evaluate2("4 // 2");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 2);

r = e.evaluate2("4 / 2");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::real8);
CHECK(r.result.f64 == 2);
}

TEST_CASE("PythonCompiler i32 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<PythonCompiler::EvalResult>

r = e.evaluate2("i: i32");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::none);
r = e.evaluate2("i = 5");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::statement);
r = e.evaluate2("i");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 5);

r = e.evaluate2("j: i32 = 9");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::none);
r = e.evaluate2("j");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 9);

r = e.evaluate2("i + j");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 14);
}

TEST_CASE("PythonCompiler i64 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<PythonCompiler::EvalResult>

r = e.evaluate2("i64(1)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 1);

r = e.evaluate2("i64(1) + i64(2)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 3);

r = e.evaluate2("i64(1) - i64(2)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == -1);

r = e.evaluate2("i64(1) * i64(2)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 2);

r = e.evaluate2("i64(3) ** i64(3)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 27);

r = e.evaluate2("i64(4) // i64(2)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 2);

r = e.evaluate2("i64(4) / i64(2)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::real8);
CHECK(r.result.f64 == 2);
}

TEST_CASE("PythonCompiler i64 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<PythonCompiler::EvalResult>

r = e.evaluate2("i: i64");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::none);
r = e.evaluate2("i = i64(5)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::statement);
r = e.evaluate2("i");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 5);

r = e.evaluate2("j: i64 = i64(9)");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::none);
r = e.evaluate2("j");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 9);

r = e.evaluate2("i + j");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer8);
CHECK(r.result.i64 == 14);
}

0 comments on commit 2420448

Please sign in to comment.