Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Support array comparison #2157

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ RUN(NAME array_size_02 LABELS cpython llvm c)
RUN(NAME array_01 LABELS cpython llvm wasm c)
RUN(NAME array_02 LABELS cpython wasm c)
RUN(NAME array_03 LABELS cpython llvm c)
RUN(NAME array_04 LABELS cpython llvm c)
RUN(NAME bindc_01 LABELS cpython llvm c)
RUN(NAME bindc_02 LABELS cpython llvm c)
RUN(NAME bindc_04 LABELS llvm c NOFAST)
Expand Down
19 changes: 19 additions & 0 deletions integration_tests/array_04.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from lpython import i32, Const
from numpy import empty, int32

def main0():
n: Const[i32] = 1
x: i32[n, n] = empty([n, n], dtype=int32)
y: i32[n, n] = empty([n, n], dtype=int32)

x[0, 0] = -10
y[0, 0] = -10

print(x[0, 0], y[0, 0])
assert x == y

y[0, 0] = 10
print(x[0, 0], y[0, 0])
assert x != y

main0()
6 changes: 6 additions & 0 deletions src/libasr/asr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -1868,6 +1868,12 @@ static inline int64_t get_fixed_size_of_array(ASR::dimension_t* m_dims, size_t n
return array_size;
}

static inline int64_t get_fixed_size_of_array(ASR::ttype_t* type) {
ASR::dimension_t* m_dims = nullptr;
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(type, m_dims);
return ASRUtils::get_fixed_size_of_array(m_dims, n_dims);
}

inline int extract_n_dims_from_ttype(ASR::ttype_t *x) {
ASR::dimension_t* m_dims_temp = nullptr;
return extract_dimensions_from_ttype(x, m_dims_temp);
Expand Down
31 changes: 31 additions & 0 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6157,6 +6157,37 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
if( ASR::is_a<ASR::Enum_t>(*dest_type) || ASR::is_a<ASR::Const_t>(*dest_type) ) {
dest_type = ASRUtils::get_contained_type(dest_type);
}

if (ASRUtils::is_array(dest_type)) {
ASR::dimension_t* m_dims = nullptr;
int n_dims = ASRUtils::extract_dimensions_from_ttype(dest_type, m_dims);
int array_size = ASRUtils::get_fixed_size_of_array(m_dims, n_dims);
if (array_size == -1) {
throw SemanticError("The truth value of an array is ambiguous. Use a.any() or a.all()", x.base.base.loc);
} else if (array_size != 1) {
throw SemanticError("The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()", x.base.base.loc);
} else {
Vec<ASR::array_index_t> argsL, argsR;
argsL.reserve(al, 1);
argsR.reserve(al, 1);
for (int i = 0; i < n_dims; i++) {
ASR::array_index_t aiL, aiR;
ASR::ttype_t *int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 4));
ASR::expr_t* const_zero = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, x.base.base.loc, 0, int_type));
aiL.m_right = aiR.m_right = const_zero;
aiL.m_left = aiR.m_left = nullptr;
aiL.m_step = aiR.m_step = nullptr;
aiL.loc = left->base.loc;
aiR.loc = right->base.loc;
argsL.push_back(al, aiL);
argsR.push_back(al, aiR);
}
dest_type = ASRUtils::type_get_past_array(dest_type);
left = ASRUtils::EXPR(make_ArrayItem_t(al, left->base.loc, left, argsL.p, argsL.n, dest_type, ASR::arraystorageType::RowMajor, nullptr));
right = ASRUtils::EXPR(make_ArrayItem_t(al, right->base.loc, right, argsR.p, argsR.n, dest_type, ASR::arraystorageType::RowMajor, nullptr));
}
}

if (ASRUtils::is_integer(*dest_type)) {
if (ASRUtils::expr_value(left) != nullptr && ASRUtils::expr_value(right) != nullptr) {
int64_t left_value = -1;
Expand Down
28 changes: 28 additions & 0 deletions tests/errors/arrays_02.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from lpython import (i8, i32, dataclass)
from numpy import (empty, int8)

@dataclass
class Foo:
a : i8[4] = empty(4, dtype=int8)
dim : i32 = 4

def trinary_majority(x : Foo, y : Foo, z : Foo) -> Foo:
foo : Foo = Foo()
i : i32
for i in range(foo.dim):
foo.a[i] = (x.a[i] & y.a[i]) | (y.a[i] & z.a[i]) | (z.a[i] & x.a[i])
return foo


t1 : Foo = Foo()
t1.a = empty(4, dtype=int8)

t2 : Foo = Foo()
t2.a = empty(4, dtype=int8)

t3 : Foo = Foo()
t3.a = empty(4, dtype=int8)

r1 : Foo = trinary_majority(t1, t2, t3)

assert r1.a == t1.a
13 changes: 13 additions & 0 deletions tests/reference/asr-arrays_02-da94458.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"basename": "asr-arrays_02-da94458",
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
"infile": "tests/errors/arrays_02.py",
"infile_hash": "05e70a0056dc67dbf3a54ea66965db8746f9de012561ca95cb1fdb43",
"outfile": null,
"outfile_hash": null,
"stdout": null,
"stdout_hash": null,
"stderr": "asr-arrays_02-da94458.stderr",
"stderr_hash": "dc0e5be7cd6de7395421aedf1ce11977206f3e35bb7cba271aed8992",
"returncode": 2
}
5 changes: 5 additions & 0 deletions tests/reference/asr-arrays_02-da94458.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
semantic error: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this:

Suggested change
semantic error: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
semantic error: The truth value of an array with more than one element is ambiguous. Use any() or all()

--> tests/errors/arrays_02.py:28:8
|
28 | assert r1.a == t1.a
| ^^^^^^^^^^^^
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this:

help: use any(r1.a == t1.a) or all(r1.a == t1.a)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

help: use any(r1.a == t1.a) or all(r1.a == t1.a)

Here, we do not have access to the string r1.a == t1.a. When printing diagnostics the input file is read (from disk) and the error line/string is obtained form the read source input.

Shall we do the following?

help: use any() or all()

Or shall we keep the message as it is currently in the main branch?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have access to AST and partial ASR, so we should be able to construct t1, r1 and a. And we know it's a struct access and we know it's a comparison. So you use this information to create the text any(r1.a == t1.a).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this #2159, so that we don't forget.

4 changes: 4 additions & 0 deletions tests/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,10 @@ asr = true
filename = "errors/arrays_01.py"
asr = true

[[test]]
filename = "errors/arrays_02.py"
asr = true

[[test]]
filename = "errors/structs_02.py"
asr = true
Expand Down